Update an endpoint
Partial update — send only the fields to change, at least one; an unknown field is a 400. A new url goes through the SSRF check again. description: null clears the description; leaving the field out keeps it. active: false pauses the endpoint, true resumes it — and resuming counts against the plan cap on active endpoints like creating one: 403 webhook_quota_exceeded when another endpoint already fills it. The signing secret is not changed here — see rotate_secret.
Authorizations
Section titled “ Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “ Path Parameters ”The endpoint id, from POST /v1/webhooks or GET /v1/webhooks.
Request Bodyrequired
Section titled “ Request Bodyrequired ”object
false pauses the endpoint (no deliveries are queued for it); true resumes it.
Jurisdiction codes ("CW", "UKGC" — see GET /v1/jurisdictions) this endpoint wants events for. Empty = every jurisdiction. Applies to every event that is about one jurisdiction: license.*, domain.listed, domain.delisted, regulatory_action.added, coverage.*. A code we do not cover is a 400 invalid_jurisdiction that lists the valid ones.
Example
{ "active": false}Responses
Section titled “ Responses ”The endpoint after the update.
object
Jurisdiction filter; empty = every jurisdiction.
Not in the POST /v1/webhooks response (nothing has been delivered yet); null until the first successful delivery.
The outcome of the latest attempt: success, retrying (failed, a retry is scheduled) or failed (abandoned after the last retry). Not in the POST /v1/webhooks response.
Not in the POST /v1/webhooks response.
Headers
Section titled “ Headers ”Your plan’s monthly request quota (not the per-second limit). Not sent on a plan with no monthly quota (Business, Enterprise).
What is left of the monthly quota, this request counted. Not sent on a plan with no monthly quota.
Unix epoch seconds of the start of the next UTC month. Not sent on a plan with no monthly quota.
tier=unlimited on a plan with no monthly quota; otherwise not sent.
Always https://igregulator.io/pricing.
The monthly request quota of your plan, or unlimited.
Requests counted this UTC month, this one included (a request that ends in 4xx / 5xx is not counted). Not sent when the limit is unlimited.
What is left of the monthly quota. Not sent when unlimited.
When the monthly counter starts again: the first of next month, 00:00 UTC, ISO-8601. Not sent when unlimited.
80% of monthly limit used — sent from 80% of the quota on, absent before.
id is not a UUID; the body is not JSON, has an unknown field or no field at all; an unknown event type; or a URL the SSRF policy refuses.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Examples
{ "error": "id must be UUID", "code": "invalid_query", "details": { "reason": "invalid_input", "field": "id", "suggestion": "Use the id returned from POST /v1/webhooks." }}{ "error": "invalid patch body", "code": "invalid_query", "details": { "reason": "invalid_input", "suggestion": "Only url, description, events, active, watchlist_only, jurisdictions may be patched." }}{ "error": "no fields to update", "code": "invalid_query", "details": { "reason": "invalid_input", "suggestion": "Pass at least one of url / description / events / active / watchlist_only / jurisdictions." }}{ "error": "unknown event type(s)", "code": "invalid_query", "details": { "reason": "invalid_event_type", "field": "events", "suggestion": "Unknown: license.changed. Valid types: license.status_changed, license.expiring_30d, license.expiring_60d, license.expiring_90d, license.expired, license.issued, domain.listed, domain.delisted, regulatory_action.added, coverage.degraded, coverage.restored, webhook.endpoint_degraded." }}{ "error": "unknown jurisdiction code(s)", "code": "invalid_query", "details": { "reason": "invalid_jurisdiction", "field": "jurisdictions", "suggestion": "Unknown: XX. Covered: AN, BE, CO, CW, DE, ES, IOM, KH, MGA, ON, SE, TGC, UA, UKGC. Omit the field or pass [] for all." }}{ "error": "webhook URL rejected by SSRF policy", "code": "invalid_query", "details": { "reason": "private_ip_blocked", "field": "url", "suggestion": "Webhook URLs must resolve to a publicly routable host. For local development use a tunnel (ngrok, cloudflared) or a service like webhook.site." }}The API key is missing, malformed, unknown or revoked. On an endpoint that works without a key this is only ever sent when a key WAS sent and is not valid — drop the header, or fix the key.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Examples
{ "error": "Authorization header required", "code": "auth_required", "details": { "reason": "api_key_missing", "suggestion": "Attach an API key: `Authorization: Bearer <key>`. No key yet? Start a 14-day free trial of Starter (card required) at https://app.igregulator.io/signup; an existing account creates keys at https://app.igregulator.io/api-keys." }}{ "error": "Authorization header must be \"Bearer <key>\"", "code": "auth_invalid", "details": { "reason": "malformed_header", "suggestion": "Header format: `Authorization: Bearer <your-api-key>`." }}{ "error": "API key not recognized", "code": "auth_invalid", "details": { "reason": "api_key_invalid", "suggestion": "Double-check the key. Create a new one at https://app.igregulator.io/api-keys if the previous one was deleted." }}{ "error": "API key has been revoked", "code": "auth_revoked", "details": { "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored." }}The key’s plan does not cover this request: the account has no plan or a canceled one (plan_inactive), or its plan’s end date has passed (plan_ended — keys, watchlist and webhook endpoints are kept, and no webhook is sent until the plan is renewed). A trial account is served as Starter. Paid plans are not on sale yet: email founder@igregulator.io and we will sort it out.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Examples
{ "error": "Active subscription required", "code": "payment_required", "details": { "reason": "plan_inactive", "suggestion": "Current plan_tier: none — this account has no active plan. Renew or choose a plan at https://app.igregulator.io/billing (by card, or by invoice for three months or more; Starter starts with a 14-day free trial, card required), or email founder@igregulator.io." }}{ "error": "Plan ended", "code": "payment_required", "details": { "reason": "plan_ended", "suggestion": "This account's business plan ended on 2027-01-22 (UTC). Keys and settings are kept; email founder@igregulator.io to renew." }}active: true on a paused endpoint while the plan’s cap on active endpoints is already filled by others. Pause or delete one first.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Example
{ "error": "Webhook endpoint limit reached", "code": "quota_exceeded", "details": { "reason": "webhook_quota_exceeded", "current_usage": 1, "limit": 1, "plan_tier": "starter", "suggestion": "Plan \"starter\" allows 1 active endpoints. Pause or delete an existing endpoint. Higher limits: Pro and Business, by card or by invoice (three months or more) — https://app.igregulator.io/billing, or email founder@igregulator.io." }}No endpoint with that id on this account — unknown, or owned by another user.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Example
{ "error": "webhook not found", "code": "not_found", "details": { "reason": "webhook_not_found", "suggestion": "The id is either invalid or owned by another user." }}A limit of the key was reached. quota_exceeded / monthly_request_limit_reached: the plan’s monthly request quota — wait for reset_at. rate_limited / per_second_limit_exceeded: more requests in one second than the plan allows — retry after Retry-After (1 s). A request refused here is not counted against the monthly quota.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Examples
{ "error": "Monthly quota exceeded", "code": "quota_exceeded", "details": { "reason": "monthly_request_limit_reached", "current_usage": 10000, "limit": 10000, "reset_at": "2026-11-01T00:00:00.000Z", "plan_tier": "starter", "suggestion": "Wait until the monthly reset (reset_at). Higher limits: Pro and Business, by card or by invoice (three months or more) — https://app.igregulator.io/billing, or email founder@igregulator.io." }}{ "error": "Per-second rate limit reached", "code": "rate_limited", "details": { "reason": "per_second_limit_exceeded", "current_usage": 6, "limit": 5, "plan_tier": "starter", "suggestion": "Your plan allows 5 req/s. Back off for a second and retry. Higher limits: Pro and Business, by card or by invoice (three months or more) — https://app.igregulator.io/billing, or email founder@igregulator.io." }}Headers
Section titled “ Headers ”On the per-second limit (1). Not on the monthly quota — read details.reset_at.
On the per-second limit only: the requests per second your plan allows.
On the per-second limit only: 0.
On the per-second limit only: Unix epoch seconds of the next second.
On the monthly quota only: the quota of your plan.
On the monthly quota only: requests counted this month.
On the monthly quota only: 0.
On the monthly quota only: when the counter starts again (ISO-8601).
Unexpected server error. Safe to retry.
The body of every non-2xx response.
object
Human-readable summary. The wording can change; do not branch on it.
The error class. Mostly one per HTTP status, with two exceptions to know: quota_exceeded is a 429 for the monthly request quota and a 403 for a plan cap (watchlist size, webhook endpoints). A 409 carries conflict (it carried invalid_query before 1.24.0). Branch on the HTTP status and details.reason. forbidden is only ever sent to a signed-in MCP connection, never to an API key.
Always present. reason is always set; field and suggestion when they apply; limit errors add the numbers below.
object
Machine-readable refinement of the top-level code — branch on this. Values: invalid_input, missing_required_parameter, conflicting_parameters, not_a_valid_hostname, hostname_too_long, invalid_pagination, invalid_cursor, since_exceeds_retention_window, invalid_event_type, invalid_jurisdiction, as_of_not_supported, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, plan_inactive, plan_ended, export_requires_pro, geo_checks_require_business, watchlist_quota_exceeded, webhook_quota_exceeded, operator_not_found, license_not_found, jurisdiction_not_found, webhook_not_found, dataset_not_found, route_not_found, method_not_allowed, watchlist_duplicate, no_active_secret, quota_exceeded, monthly_request_limit_reached, per_second_limit_exceeded, watchlist_events_poll_limit, export_daily_limit_reached, geo_check_quota_exceeded, internal_error. A rejected webhook URL carries the SSRF check’s reason (invalid_url, invalid_scheme, empty_host, blocked_hostname, unresolvable_host, private_ip_blocked). New values can be added.
Present only when the error maps to a specific request input (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
A hint a person or an agent can act on. Present on every error today.
On a limit error (429, and the 403 plan caps): the ceiling that was reached.
On a keyed limit error: how much of limit is used. Not on the keyless per-IP 429 or the watchlist-poll 429.
When the counter starts again — on the keyless per-IP 429, the monthly quota, the watchlist-poll limit and the export daily limit. Not on the per-second limit (retry after one second).
The key’s plan, on plan-scoped limit errors and on export_requires_pro.
On export_requires_pro: the lowest plan that includes the feature.
On watchlist_events_poll_limit: always hour.
Example
{ "error": "Internal server error", "code": "server_error", "details": { "reason": "internal_error", "suggestion": "Retry with exponential backoff (1s / 2s / 4s). If the error persists past 4 seconds, surface failure state to the user instead of looping." }}