Creates a webhook subscription.
const url = 'https://api.featureflip.io/api/v1/orgs/example/webhooks';const options = { method: 'POST', headers: {Authorization: '<Authorization>', 'Content-Type': 'application/json'}, body: '{"name":"Checkout flag changes to Slack relay","url":"https://hooks.acme.example/featureflip","provider":"GenericHttp","eventTypes":["flag.toggled","flag.updated"],"projectIds":["0197b69f-1a2b-7c3d-8e4f-5a6b7c8d9e0f"],"environmentIds":["0197b69f-2b3c-7d4e-9f5a-6b7c8d9e0f1a"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.featureflip.io/api/v1/orgs/example/webhooks \ --header 'Authorization: <Authorization>' \ --header 'Content-Type: application/json' \ --data '{ "name": "Checkout flag changes to Slack relay", "url": "https://hooks.acme.example/featureflip", "provider": "GenericHttp", "eventTypes": [ "flag.toggled", "flag.updated" ], "projectIds": [ "0197b69f-1a2b-7c3d-8e4f-5a6b7c8d9e0f" ], "environmentIds": [ "0197b69f-2b3c-7d4e-9f5a-6b7c8d9e0f1a" ] }'Requires Admin. The response carries the signing secret,
which is never shown again. Supports the Idempotency-Key header.
Authorizations
Section titled “ Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “ Path Parameters ”Request Body
Section titled “ Request Body ”Creates a webhook subscription. provider is GenericHttp. Omit eventTypes,
projectIds or environmentIds (or send an empty list) to receive every event,
project or environment. A token restricted to specific projects must list at least one project,
all of them within its allowlist.
object
Allowed values: GenericHttp.
Example
{ "name": "Checkout flag changes to Slack relay", "url": "https://hooks.acme.example/featureflip", "provider": "GenericHttp", "eventTypes": [ "flag.toggled", "flag.updated" ], "projectIds": [ "0197b69f-1a2b-7c3d-8e4f-5a6b7c8d9e0f" ], "environmentIds": [ "0197b69f-2b3c-7d4e-9f5a-6b7c8d9e0f1a" ]}Creates a webhook subscription. provider is GenericHttp. Omit eventTypes,
projectIds or environmentIds (or send an empty list) to receive every event,
project or environment. A token restricted to specific projects must list at least one project,
all of them within its allowlist.
object
Allowed values: GenericHttp.
Example
{ "name": "Checkout flag changes to Slack relay", "url": "https://hooks.acme.example/featureflip", "provider": "GenericHttp", "eventTypes": [ "flag.toggled", "flag.updated" ], "projectIds": [ "0197b69f-1a2b-7c3d-8e4f-5a6b7c8d9e0f" ], "environmentIds": [ "0197b69f-2b3c-7d4e-9f5a-6b7c8d9e0f1a" ]}Creates a webhook subscription. provider is GenericHttp. Omit eventTypes,
projectIds or environmentIds (or send an empty list) to receive every event,
project or environment. A token restricted to specific projects must list at least one project,
all of them within its allowlist.
object
Allowed values: GenericHttp.
Example
{ "name": "Checkout flag changes to Slack relay", "url": "https://hooks.acme.example/featureflip", "provider": "GenericHttp", "eventTypes": [ "flag.toggled", "flag.updated" ], "projectIds": [ "0197b69f-1a2b-7c3d-8e4f-5a6b7c8d9e0f" ], "environmentIds": [ "0197b69f-2b3c-7d4e-9f5a-6b7c8d9e0f1a" ]}Responses
Section titled “ Responses ”Created
The created subscription’s id and its signing secret. The secret is shown only here.
object
Example
{ "id": "0197b6a4-6f7a-7b8c-9d0e-1f2a3b4c5d6e", "secret": "whsec_q2Vb8XJ1s0mYpZ4tK7wRr3uN9cL6aD5eF1gH2iJ3kL4=", "warning": "Store this secret securely — it will not be shown again."}Headers
Section titled “ Headers ”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Bad Request
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean, next_actions and connection_id are ADDITIVE optional keys
(null → omitted via the global DefaultIgnoreCondition = WhenWritingNull), so
pre-existing error bodies are byte-for-byte unchanged when they’re absent.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “ Headers ”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Authentication is required, or the supplied API token is invalid or expired.
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean, next_actions and connection_id are ADDITIVE optional keys
(null → omitted via the global DefaultIgnoreCondition = WhenWritingNull), so
pre-existing error bodies are byte-for-byte unchanged when they’re absent.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “ Headers ”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Forbidden
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean, next_actions and connection_id are ADDITIVE optional keys
(null → omitted via the global DefaultIgnoreCondition = WhenWritingNull), so
pre-existing error bodies are byte-for-byte unchanged when they’re absent.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “ Headers ”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Not Found
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean, next_actions and connection_id are ADDITIVE optional keys
(null → omitted via the global DefaultIgnoreCondition = WhenWritingNull), so
pre-existing error bodies are byte-for-byte unchanged when they’re absent.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “ Headers ”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Rate limit exceeded. Retry after the interval indicated by the Retry-After header.
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean, next_actions and connection_id are ADDITIVE optional keys
(null → omitted via the global DefaultIgnoreCondition = WhenWritingNull), so
pre-existing error bodies are byte-for-byte unchanged when they’re absent.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “ Headers ”Number of seconds to wait before retrying the request.
The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.