{"openapi":"3.1.0","info":{"title":"Base44 Outbound Webhooks API","description":"\nRegister HTTPS endpoints that Base44 notifies when something happens in your workspace, such as an\napp being published or the AI finishing a message. The events section lists every event an\nendpoint can receive.\n\n**Authentication:** send a workspace API key with the `outbound_webhooks:write` scope as\n`Authorization: Bearer <key>`. The key decides the workspace, so no path takes a workspace ID.\nThe public key set needs no authentication.\n\n**Activation:** registering an endpoint sends it a signed `webhook.test.v1` event in the same call.\nThe endpoint becomes `active` only if it answers with a 2xx status within 5 seconds and returns the\nevent's `data.challenge` in its response body, either as `{\"challenge\": \"<value>\"}` or as the bare\nvalue. Until then it receives nothing else.\n\n**Events:** each event is a CloudEvents 1.0 JSON body, signed with Ed25519 under the Standard Webhooks\n`v1a` scheme. Verify every request against your workspace's public key set, and deduplicate on `id`:\ndelivery is at least once and unordered.\n\n**Rate limits**, per workspace and multiplied by your plan's rate-limit tier:\n- endpoint reads (list, get): 300 a minute\n- endpoint writes (register, update, pause, resume, delete): 60 a minute\n- activation tests (register, test, resuming an auto-paused endpoint): 10 a minute\n- the public key set: 600 a minute per client IP\n\nA `429` carries `Retry-After`. Errors use one envelope, `{\"error\": {\"code\", \"message\", \"details\"}}`;\nmatch on `error.code`, never on the message.\n","version":"1.0.0"},"paths":{"/endpoints":{"get":{"tags":["outbound-webhooks"],"summary":"List endpoints","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nLists the workspace's endpoints, oldest first. When `next_cursor` is set, pass it back as `cursor` for the next page.","operationId":"list_endpoints_endpoints_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"How many endpoints to return.","examples":[10],"default":50,"title":"Limit"},"description":"How many endpoints to return."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` from the previous page. Omit it for the first page.","examples":["eyJpZCI6IjZhYzJhODJlZGZhZmQxYjZjNmE5YzI3ZCJ9"],"title":"Cursor"},"description":"The `next_cursor` from the previous page. Omit it for the first page."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointListResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"post":{"tags":["outbound-webhooks"],"summary":"Register an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nRegisters an endpoint and tests it in the same call. The test is a signed `webhook.test.v1` event. The endpoint activates only if it answers with a 2xx status within 5 seconds and returns the event's `data.challenge` in its response body. `activated` says whether it did; when it didn't, `failure_category`, `http_status` and `detail` say why. The response is `201` either way, because the endpoint was created: retry a failed test with `POST /endpoints/{endpoint_id}/test`, not by registering again. Registering isn't idempotent: if you lose the response, list the endpoints before retrying. A workspace can have up to 10 endpoints.","operationId":"register_endpoint_endpoints_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/endpoints/{endpoint_id}":{"get":{"tags":["outbound-webhooks"],"summary":"Get an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nReturns one endpoint, including its state and delivery health.","operationId":"get_endpoint_endpoints__endpoint_id__get","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","description":"The endpoint's ID.","examples":["6ac2a82edfafd1b6c6a9c27d"],"title":"Endpoint Id"},"description":"The endpoint's ID."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"patch":{"tags":["outbound-webhooks"],"summary":"Update an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nChanges an endpoint's URL, event types or description. Send only the fields to change. A new `target_url` returns the endpoint to `pending` until it passes `POST /endpoints/{endpoint_id}/test`.","operationId":"update_endpoint_endpoints__endpoint_id__patch","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","description":"The endpoint's ID.","examples":["6ac2a82edfafd1b6c6a9c27d"],"title":"Endpoint Id"},"description":"The endpoint's ID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"delete":{"tags":["outbound-webhooks"],"summary":"Delete an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nDeletes the endpoint and stops sending to its URL. Events not yet delivered to it aren't sent.","operationId":"delete_endpoint_endpoints__endpoint_id__delete","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","description":"The endpoint's ID.","examples":["6ac2a82edfafd1b6c6a9c27d"],"title":"Endpoint Id"},"description":"The endpoint's ID."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointDeletedResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/endpoints/{endpoint_id}/test":{"post":{"tags":["outbound-webhooks"],"summary":"Test an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nSends the activation test again, for an endpoint that didn't activate or whose URL changed. The test is a signed `webhook.test.v1` event. The endpoint activates only if it answers with a 2xx status within 5 seconds and returns the event's `data.challenge` in its response body. `activated` says whether it did; when it didn't, `failure_category`, `http_status` and `detail` say why. Testing an active endpoint leaves it active, and testing a paused one leaves it paused.","operationId":"test_endpoint_endpoints__endpoint_id__test_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","description":"The endpoint's ID.","examples":["6ac2a82edfafd1b6c6a9c27d"],"title":"Endpoint Id"},"description":"The endpoint's ID."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/endpoints/{endpoint_id}/pause":{"post":{"tags":["outbound-webhooks"],"summary":"Pause an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nStops sending events to the endpoint, for example while its receiver is redeployed. Deliveries already waiting are sent after it resumes. Events that happen while it's paused aren't sent to it, unless it resumes within seconds, before they're dispatched.","operationId":"pause_endpoint_endpoints__endpoint_id__pause_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","description":"The endpoint's ID.","examples":["6ac2a82edfafd1b6c6a9c27d"],"title":"Endpoint Id"},"description":"The endpoint's ID."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/endpoints/{endpoint_id}/resume":{"post":{"tags":["outbound-webhooks"],"summary":"Resume an endpoint","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nResumes a paused endpoint. One you paused resumes right away. One Base44 paused after repeated failures (`auto_paused`) must pass the activation test again, which runs in the same call: The test is a signed `webhook.test.v1` event. The endpoint activates only if it answers with a 2xx status within 5 seconds and returns the event's `data.challenge` in its response body. `activated` says whether it did; when it didn't, `failure_category`, `http_status` and `detail` say why.","operationId":"resume_endpoint_endpoints__endpoint_id__resume_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","description":"The endpoint's ID.","examples":["6ac2a82edfafd1b6c6a9c27d"],"title":"Endpoint Id"},"description":"The endpoint's ID."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"`unauthenticated` — a missing, malformed, unknown or disabled credential. Not distinguished further on purpose.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"unauthenticated","message":"Invalid workspace API key.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"`permission_denied`: the key lacks the `outbound_webhooks:write` scope, or the workspace's plan doesn't include outbound webhooks.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"permission_denied","message":"This workspace API key is not permitted to manage outbound webhooks. Needed: [outbound_webhooks:write]","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"`not_found` — no such endpoint in this workspace. Also returned for another workspace's endpoint id, so the response does not confirm it exists.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"not_found","message":"Webhook endpoint not found.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"`conflict` — the endpoint changed under the request; re-read and retry. `limit_exceeded` — the workspace is at its endpoint cap (`details.max_endpoints`); not retryable until an endpoint is deleted.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"limit_exceeded","message":"A workspace may have at most 10 webhook endpoints.","details":{"max_endpoints":10}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error`: an unexpected failure. Retry with exponential backoff.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/workspaces/{workspace_id}/keys":{"get":{"tags":["outbound-webhooks"],"summary":"Get the public key set","description":"<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>\n\nReturns the public keys that verify the workspace's event signatures. Needs no authentication. An unknown workspace, or one with no keys yet, gets an empty `keys` list.\n\nKeys come newest first, a page at a time; follow `next_cursor` until it's null. A workspace holds one key, or two during a rotation, so the default page is usually the whole set.\n\nThe signature header carries no key ID, so try every key, and fetch the set again once when none verifies. During a key rotation, events carry one signature per key. Responses carry an `ETag`; send it back as `If-None-Match` to get `304 Not Modified` when nothing changed. A non-empty set may be cached for 5 minutes. Rate limit: 600 requests a minute per client IP.","operationId":"get_public_key_set_workspaces__workspace_id__keys_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","description":"The workspace's ID.","examples":["67f3954555578059d9273f7e"],"title":"Workspace Id"},"description":"The workspace's ID."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"How many keys to return.","examples":[10],"default":10,"title":"Limit"},"description":"How many keys to return."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The `next_cursor` from the previous page. Omit it for the first page.","examples":["gAAAAABn7vJx..."],"title":"Cursor"},"description":"The `next_cursor` from the previous page. Omit it for the first page."},{"name":"if-none-match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-None-Match"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicKeySetResponse"}}},"headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}},"ETag":{"description":"Send it back as `If-None-Match`.","schema":{"type":"string"}},"Cache-Control":{"description":"`public, max-age=300` for a non-empty set.","schema":{"type":"string"}}}},"400":{"description":"`invalid_request` — a malformed body, an unusable target URL, an unknown event type, or an invalid or expired cursor.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"fields":[{"field":"target_url","problem":"Field required"}]}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"`rate_limited` — request throttling. Retryable; honour `Retry-After`.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, in Unix seconds.","schema":{"type":"integer"}}},"content":{"application/json":{"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Retry after the interval in the Retry-After header.","details":{"retry_after_seconds":42}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"`internal_error` — an unexpected failure. With `details.reason: replacement_mint_failed`, a signing-key revoke took effect but its replacement was not created; repeat the revoke to create it.","headers":{"X-Request-Id":{"description":"Identifies this request. Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"example":{"error":{"code":"internal_error","message":"An internal error occurred. Retry with exponential backoff.","details":{}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[]}}},"components":{"schemas":{"ActivationResponse":{"properties":{"endpoint":{"$ref":"#/components/schemas/EndpointResponse"},"activated":{"type":"boolean","title":"Activated","description":"Whether the endpoint passed the test and is `active`."},"http_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Http Status","description":"The status your endpoint answered with. Null when it didn't answer."},"failure_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Category","description":"Why the test failed: `timeout`, `transport` (no connection), `server_error` (5xx), `client_error` (4xx, or a 2xx without the challenge), `redirect`, `ssrf_rejected` (the URL resolved to a non-public address) or `internal`. Null on success."},"detail":{"type":"string","title":"Detail","description":"A sentence explaining the result. Not a stable contract.","default":""}},"type":"object","required":["endpoint","activated"],"title":"ActivationResponse","description":"The endpoint and the result of its activation test.","examples":[{"activated":true,"detail":"","endpoint":{"activated_at":"2026-10-04T19:25:39.423Z","consecutive_failed_deliveries":0,"created_date":"2026-10-04T19:25:34.260Z","description":"Provisioning","health":"healthy","id":"6ac2a82edfafd1b6c6a9c27d","last_success_at":"2026-10-05T13:23:36.743Z","selected_event_types":["app.created.v1","app.deleted.v1"],"state":"active","target_url":"https://hooks.example.com/base44"},"http_status":200}]},"ApiErrorBody":{"properties":{"code":{"type":"string","title":"Code","description":"Stable machine-readable cause. Match on this, not the message."},"message":{"type":"string","title":"Message","description":"Human-readable prose. Not a stable contract."},"details":{"additionalProperties":true,"type":"object","title":"Details","description":"Documented structured context, or empty."}},"type":"object","required":["code","message"],"title":"ApiErrorBody"},"ApiErrorResponse":{"properties":{"error":{"$ref":"#/components/schemas/ApiErrorBody","description":"What went wrong."}},"type":"object","required":["error"],"title":"ApiErrorResponse"},"EndpointCreateRequest":{"properties":{"target_url":{"type":"string","maxLength":2048,"title":"Target Url","description":"The HTTPS URL that receives events. It must resolve to public addresses, can't contain credentials, and must answer directly: redirects aren't followed."},"selected_event_types":{"items":{"type":"string"},"type":"array","maxItems":64,"minItems":1,"title":"Selected Event Types","description":"The event types to send, such as `app.created.v1`. Each type is a separate version."},"description":{"type":"string","maxLength":200,"title":"Description","description":"A note for your own reference, up to 200 characters.","default":""}},"additionalProperties":false,"type":"object","required":["target_url","selected_event_types"],"title":"EndpointCreateRequest","examples":[{"description":"Production receiver","selected_event_types":["app.created.v1","app.deleted.v1"],"target_url":"https://hooks.example.com/base44"}]},"EndpointDeletedResponse":{"properties":{"id":{"type":"string","title":"Id","description":"The endpoint's ID."},"deleted":{"type":"boolean","title":"Deleted","description":"Always `true`.","default":true}},"type":"object","required":["id"],"title":"EndpointDeletedResponse","examples":[{"deleted":true,"id":"6ac2a82edfafd1b6c6a9c27d"}]},"EndpointHealth":{"type":"string","enum":["unknown","healthy","degraded","failing"],"title":"EndpointHealth","description":"How recent deliveries to the endpoint went."},"EndpointListResponse":{"properties":{"endpoints":{"items":{"$ref":"#/components/schemas/EndpointResponse"},"type":"array","title":"Endpoints","description":"This page of endpoints, oldest first."},"max_endpoints":{"type":"integer","title":"Max Endpoints","description":"How many endpoints the workspace can have.","default":10},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Opaque continuation token. Absent or null on the last page. Pass it back as `cursor`; do not construct or parse one."}},"type":"object","required":["endpoints"],"title":"EndpointListResponse","examples":[{"endpoints":[{"activated_at":"2026-10-04T19:25:39.423Z","consecutive_failed_deliveries":0,"created_date":"2026-10-04T19:25:34.260Z","description":"Provisioning","health":"healthy","id":"6ac2a82edfafd1b6c6a9c27d","last_success_at":"2026-10-05T13:23:36.743Z","selected_event_types":["app.created.v1","app.deleted.v1"],"state":"active","target_url":"https://hooks.example.com/base44"}],"max_endpoints":10}]},"EndpointResponse":{"properties":{"id":{"type":"string","title":"Id","description":"The endpoint's ID."},"target_url":{"type":"string","title":"Target Url","description":"The URL that receives events."},"description":{"type":"string","title":"Description","description":"A note for your own reference, up to 200 characters."},"selected_event_types":{"items":{"type":"string"},"type":"array","title":"Selected Event Types","description":"The event types sent to this endpoint."},"state":{"$ref":"#/components/schemas/EndpointState","description":"`pending` until it passes the activation test, then `active`. `paused` when you paused it, `auto_paused` when Base44 paused it after 10 failed deliveries in a row over at least 5 days. Only `active` endpoints receive events."},"health":{"$ref":"#/components/schemas/EndpointHealth","description":"How recent deliveries went. `unknown` before the first delivery, `healthy` after a success, `failing` after 3 failed deliveries in a row. `degraded` is reserved."},"created_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created Date","description":"When the endpoint was registered, in UTC."},"activated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Activated At","description":"When the endpoint first became active at its current URL, in UTC. Events from before this time aren't sent to it."},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At","description":"When a delivery last succeeded. In UTC. Absent until it first happens."},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Failure At","description":"When a delivery last ran out of attempts. In UTC. Absent until it first happens."},"consecutive_failed_deliveries":{"type":"integer","title":"Consecutive Failed Deliveries","description":"Deliveries in a row that ran out of attempts. A success resets it to 0.","default":0}},"type":"object","required":["id","target_url","description","selected_event_types","state","health"],"title":"EndpointResponse","examples":[{"activated_at":"2026-10-04T19:25:39.423Z","consecutive_failed_deliveries":0,"created_date":"2026-10-04T19:25:34.260Z","description":"Provisioning","health":"healthy","id":"6ac2a82edfafd1b6c6a9c27d","last_success_at":"2026-10-05T13:23:36.743Z","selected_event_types":["app.created.v1","app.deleted.v1"],"state":"active","target_url":"https://hooks.example.com/base44"}]},"EndpointState":{"type":"string","enum":["pending","active","paused","auto_paused"],"title":"EndpointState","description":"Whether the endpoint receives events."},"EndpointUpdateRequest":{"properties":{"target_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Target Url","description":"The HTTPS URL that receives events. It must resolve to public addresses, can't contain credentials, and must answer directly: redirects aren't followed. Changing it returns the endpoint to `pending` until it passes the activation test again."},"selected_event_types":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":64,"minItems":1},{"type":"null"}],"title":"Selected Event Types","description":"The event types to send, such as `app.created.v1`. Each type is a separate version."},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description","description":"A note for your own reference, up to 200 characters."}},"additionalProperties":false,"type":"object","title":"EndpointUpdateRequest","description":"The fields to change. A field you leave out keeps its value.","examples":[{"selected_event_types":["app.published.v1"]}]},"PublicKeySetResponse":{"properties":{"signature_scheme":{"type":"string","title":"Signature Scheme","description":"The scheme tag in the `webhook-signature` header. Always `v1a`."},"keys":{"items":{"$ref":"#/components/schemas/PublicSigningKey"},"type":"array","title":"Keys","description":"This page of keys, newest first. Empty when the workspace has none."},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Opaque continuation token. Null on the last page. Pass it back as `cursor`; a receiver needs every page to verify during a rotation."}},"type":"object","required":["signature_scheme","keys"],"title":"PublicKeySetResponse","description":"The keys that currently sign the workspace's events.","examples":[{"keys":[{"algorithm":"ed25519_v1","kid":"whk_1","public_key":"whpk_tuaUMN99+3lmXIpT0k7KusnxtBRgT5EMGAbyjTWLkJY=","valid_from":"2026-09-27T13:11:15.000Z"}],"signature_scheme":"v1a"}]},"PublicSigningKey":{"properties":{"kid":{"type":"string","title":"Kid","description":"Identifies the key in this set. Requests don't carry it."},"algorithm":{"type":"string","title":"Algorithm","description":"Always `ed25519_v1`."},"public_key":{"type":"string","title":"Public Key","description":"The `whpk_`-prefixed Ed25519 public key: standard base64 of the 32 raw key bytes. Standard Webhooks libraries accept it as is."},"valid_from":{"type":"string","title":"Valid From","description":"When the key started signing, in UTC."},"valid_until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valid Until","description":"When a key being rotated out stops signing, in UTC. Null for the current key."}},"type":"object","required":["kid","algorithm","public_key","valid_from"],"title":"PublicSigningKey"},"AppCreatedV1Data":{"title":"app.created.v1","description":"The `data` object of `app.created.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"app_type":{"description":"The kind of app. New values arrive as a new event version.","enum":["imported_app","user_agent","user_app","user_game"],"type":"string"},"created_at":{"description":"When the app was created (UTC).","format":"date-time","type":"string"}},"required":["app_id","workspace_id","owner_id","app_type","created_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","app_type":"user_app","created_at":"2026-09-01T10:15:30.123Z"}]},"AppCreatedV1Event":{"type":"object","description":"`app.created.v1`: An app was created.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"app.created.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/app.created.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/AppCreatedV1Data"}}},"AppPublishedV1Data":{"title":"app.published.v1","description":"The `data` object of `app.published.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"published_version":{"description":"Id of the version now live.","type":"string"},"published_at":{"description":"When the version went live (UTC).","format":"date-time","type":"string"}},"required":["app_id","workspace_id","owner_id","published_version","published_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","published_version":"68c2d3e4f5a6b7c8d9e0f1a2","published_at":"2026-09-01T10:15:30.123Z"}]},"AppPublishedV1Event":{"type":"object","description":"`app.published.v1`: An app version was published.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"app.published.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/app.published.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/AppPublishedV1Data"}}},"AppUnpublishedV1Data":{"title":"app.unpublished.v1","description":"The `data` object of `app.unpublished.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"unpublished_at":{"description":"When the app was taken offline (UTC).","format":"date-time","type":"string"}},"required":["app_id","workspace_id","owner_id","unpublished_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","unpublished_at":"2026-09-01T10:15:30.123Z"}]},"AppUnpublishedV1Event":{"type":"object","description":"`app.unpublished.v1`: An app was taken offline.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"app.unpublished.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/app.unpublished.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/AppUnpublishedV1Data"}}},"AppDeletedV1Data":{"title":"app.deleted.v1","description":"The `data` object of `app.deleted.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"deleted_at":{"description":"When the app was moved to trash (UTC). It can still be restored.","format":"date-time","type":"string"}},"required":["app_id","workspace_id","owner_id","deleted_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","deleted_at":"2026-09-01T10:15:30.123Z"}]},"AppDeletedV1Event":{"type":"object","description":"`app.deleted.v1`: An app was moved to trash (restorable, not erased).","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"app.deleted.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/app.deleted.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/AppDeletedV1Data"}}},"AppRestoredV1Data":{"title":"app.restored.v1","description":"The `data` object of `app.restored.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"restored_at":{"description":"When the app was restored (UTC).","format":"date-time","type":"string"}},"required":["app_id","workspace_id","owner_id","restored_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","restored_at":"2026-09-01T10:15:30.123Z"}]},"AppRestoredV1Event":{"type":"object","description":"`app.restored.v1`: An app was restored from trash.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"app.restored.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/app.restored.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/AppRestoredV1Data"}}},"ChatTurnStartedV1Data":{"title":"chat.turn_started.v1","description":"The `data` object of `chat.turn_started.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"message_id":{"description":"The message that started the turn: the id returned when you sent it, and the app's `status.turn_id` while the turn runs.","type":"string"},"conversation_id":{"description":"The conversation the message belongs to.","type":"string"},"started_at":{"description":"When the AI started working on the message (UTC).","format":"date-time","type":"string"},"continues_message_id":{"description":"Set when this turn continues one that was interrupted: the `message_id` of that turn. Follow it back to add up the time the whole response took.","type":"string"}},"required":["app_id","workspace_id","owner_id","message_id","started_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","message_id":"68d3e4f5a6b7c8d9e0f1a2b3","conversation_id":"68c2d3e4f5a6b7c8d9e0f1a2","started_at":"2026-09-01T10:15:30.123Z"}]},"ChatTurnStartedV1Event":{"type":"object","description":"`chat.turn_started.v1`: The AI started working on a message.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"chat.turn_started.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/chat.turn_started.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/ChatTurnStartedV1Data"}}},"ChatTurnEndedV1Data":{"title":"chat.turn_ended.v1","description":"The `data` object of `chat.turn_ended.v1`.","additionalProperties":false,"properties":{"app_id":{"description":"The app the event is about.","type":"string"},"workspace_id":{"description":"The workspace the app belongs to.","type":"string"},"owner_id":{"description":"Opaque platform id of the app's current owner.","type":"string"},"message_id":{"description":"The message that started the turn: the id returned when you sent it, and the app's `status.turn_id` while the turn runs.","type":"string"},"conversation_id":{"description":"The conversation the message belongs to.","type":"string"},"started_at":{"description":"When the AI started working on the message (UTC).","format":"date-time","type":"string"},"continues_message_id":{"description":"Set when this turn continues one that was interrupted: the `message_id` of that turn. Follow it back to add up the time the whole response took.","type":"string"},"status":{"description":"How the turn ended. `finished`: the AI replied and has nothing pending. `waiting_for_user_input`: the AI stopped to ask something, such as a clarifying question or a plan to approve, and continues when the next message answers it. `failed`: the turn hit an error. `cancelled`: the turn was stopped before it ended. `interrupted`: the AI was interrupted, for example by a restart, and continues the work in a new turn whose `continues_message_id` is this message.","enum":["finished","waiting_for_user_input","failed","cancelled","interrupted"],"type":"string"},"ended_at":{"description":"When the turn ended (UTC).","format":"date-time","type":"string"}},"required":["app_id","workspace_id","owner_id","message_id","started_at","status","ended_at"],"type":"object","examples":[{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","message_id":"68d3e4f5a6b7c8d9e0f1a2b3","conversation_id":"68c2d3e4f5a6b7c8d9e0f1a2","started_at":"2026-09-01T10:15:30.123Z","status":"finished","ended_at":"2026-09-01T10:19:02.456Z"}]},"ChatTurnEndedV1Event":{"type":"object","description":"`chat.turn_ended.v1`: The AI finished responding to a message.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"chat.turn_ended.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/chat.turn_ended.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/ChatTurnEndedV1Data"}}},"WebhookTestV1Data":{"title":"webhook.test.v1","description":"The `data` object of `webhook.test.v1`.","additionalProperties":false,"properties":{"endpoint_id":{"description":"The endpoint being activated.","type":"string"},"workspace_id":{"description":"The workspace the endpoint belongs to.","type":"string"},"sent_at":{"description":"When the test was sent (UTC).","format":"date-time","type":"string"},"challenge":{"description":"Return this value in your response body to activate the endpoint.","type":"string"}},"required":["endpoint_id","workspace_id","sent_at","challenge"],"type":"object","examples":[{"endpoint_id":"68d4e5f6a7b8c9d0e1f2a3b4","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","sent_at":"2026-09-01T10:15:30.123Z","challenge":"8f14e45fceea167a5a36dedd4bea2543"}]},"WebhookTestV1Event":{"type":"object","description":"`webhook.test.v1`: Endpoint activation test.","required":["specversion","id","source","type","subject","time","datacontenttype","dataschema","authtype","authid","data"],"properties":{"specversion":{"type":"string","const":"1.0"},"id":{"type":"string","description":"Unique event ID. Deduplicate on it: a retry repeats it."},"source":{"type":"string","description":"The workspace, as `https://base44.com/workspaces/<workspace_id>`."},"type":{"type":"string","const":"webhook.test.v1"},"subject":{"type":"string","description":"What the event is about: `apps/<app_id>`, or `endpoints/<endpoint_id>` for a test event."},"time":{"type":"string","format":"date-time","description":"When the event happened, in UTC. Not when it was sent."},"datacontenttype":{"type":"string","const":"application/json"},"dataschema":{"type":"string","const":"https://base44.com/webhooks/schemas/webhook.test.v1.json","description":"The JSON Schema for `data`."},"traceparent":{"type":"string","description":"W3C trace context, when the event was traced."},"tracestate":{"type":"string","description":"W3C trace state, when present."},"authtype":{"type":"string","enum":["user","service_account","api_key","system","unauthenticated","unknown"],"description":"The kind of principal that caused the event."},"authid":{"type":"string","description":"The ID of the principal that caused the event."},"data":{"$ref":"#/components/schemas/WebhookTestV1Data"}}}},"securitySchemes":{"WorkspaceApiKey":{"type":"http","scheme":"bearer","description":"A workspace API key with the `outbound_webhooks:write` scope, sent as `Authorization: Bearer <key>`."}}},"tags":[{"name":"outbound-webhooks","description":"Register and manage the endpoints that receive events, and get the keys that verify them."},{"name":"events","description":"The events Base44 sends to your endpoints."}],"servers":[{"url":"https://app.base44.com/api/v1/outbound-webhooks","description":"Outbound Webhooks API"}],"security":[{"WorkspaceApiKey":[]}],"webhooks":{"app.created.v1":{"post":{"summary":"An app was created","description":"Sent to every active endpoint that selected `app.created.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"app.created.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppCreatedV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"app.created.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/app.created.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","app_type":"user_app","created_at":"2026-09-01T10:15:30.123Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"app.published.v1":{"post":{"summary":"An app version was published","description":"Sent to every active endpoint that selected `app.published.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"app.published.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppPublishedV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"app.published.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/app.published.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","published_version":"68c2d3e4f5a6b7c8d9e0f1a2","published_at":"2026-09-01T10:15:30.123Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"app.unpublished.v1":{"post":{"summary":"An app was taken offline","description":"Sent to every active endpoint that selected `app.unpublished.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"app.unpublished.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUnpublishedV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"app.unpublished.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/app.unpublished.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","unpublished_at":"2026-09-01T10:15:30.123Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"app.deleted.v1":{"post":{"summary":"An app was moved to trash (restorable, not erased)","description":"Sent to every active endpoint that selected `app.deleted.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"app.deleted.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDeletedV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"app.deleted.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/app.deleted.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","deleted_at":"2026-09-01T10:15:30.123Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"app.restored.v1":{"post":{"summary":"An app was restored from trash","description":"Sent to every active endpoint that selected `app.restored.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"app.restored.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppRestoredV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"app.restored.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/app.restored.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","restored_at":"2026-09-01T10:15:30.123Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"chat.turn_started.v1":{"post":{"summary":"The AI started working on a message","description":"Sent to every active endpoint that selected `chat.turn_started.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"chat.turn_started.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatTurnStartedV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"chat.turn_started.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/chat.turn_started.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","message_id":"68d3e4f5a6b7c8d9e0f1a2b3","conversation_id":"68c2d3e4f5a6b7c8d9e0f1a2","started_at":"2026-09-01T10:15:30.123Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"chat.turn_ended.v1":{"post":{"summary":"The AI finished responding to a message","description":"Sent to every active endpoint that selected `chat.turn_ended.v1`. Answer with any 2xx status to acknowledge it. Anything else, a redirect, or no answer within 15 seconds counts as a failure, and the event is retried, up to 8 attempts over about 27 hours.","operationId":"chat.turn_ended.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatTurnEndedV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"chat.turn_ended.v1","subject":"apps/68b0c1d2e3f4a5b6c7d8e9f0","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/chat.turn_ended.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"app_id":"68b0c1d2e3f4a5b6c7d8e9f0","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","owner_id":"6899aabbccddeeff00112233","message_id":"68d3e4f5a6b7c8d9e0f1a2b3","conversation_id":"68c2d3e4f5a6b7c8d9e0f1a2","started_at":"2026-09-01T10:15:30.123Z","status":"finished","ended_at":"2026-09-01T10:19:02.456Z"}}}}},"responses":{"2XX":{"description":"The event was received."}}}},"webhook.test.v1":{"post":{"summary":"Endpoint activation test","description":"Sent when you register an endpoint, test it, or resume one Base44 paused. Answer with a 2xx status within 5 seconds and return `data.challenge` in the response body, as `{\"challenge\": \"<value>\"}` or as the bare value. A failed test leaves the endpoint's state unchanged and isn't retried: test the endpoint again.","operationId":"webhook.test.v1","tags":["events"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event's `id`. Identical on every attempt of the same event.","schema":{"type":"string"},"example":"evt_6a65dbeeb723cfb1a697f349"},{"name":"webhook-timestamp","in":"header","required":true,"description":"When this attempt was signed, in Unix seconds. Reject a request more than 300 seconds from your clock.","schema":{"type":"string"},"example":"1788257730"},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1a,<base64 signature>` entries, one per active signing key. Each signs `<webhook-id>.<webhook-timestamp>.<raw body>` with Ed25519. Accept the request if any entry verifies against any key in the workspace's public key set.","schema":{"type":"string"},"example":"v1a,hnO3f9T8Ytu9HwrXslvumlUpqtNVqkhqw/enGzPCXe5BdqzCInXqYXFymVJaA7AZdpXwVLPo3mNl8EM+m7TBAg=="}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestV1Event"},"example":{"specversion":"1.0","id":"evt_6a65dbeeb723cfb1a697f349","source":"https://base44.com/workspaces/68a1b2c3d4e5f6a7b8c9d0e1","type":"webhook.test.v1","subject":"endpoints/68d4e5f6a7b8c9d0e1f2a3b4","time":"2026-09-01T10:15:30.123Z","datacontenttype":"application/json","dataschema":"https://base44.com/webhooks/schemas/webhook.test.v1.json","authtype":"user","authid":"68b2c3d4e5f6a7b8c9d0e1f2","data":{"endpoint_id":"68d4e5f6a7b8c9d0e1f2a3b4","workspace_id":"68a1b2c3d4e5f6a7b8c9d0e1","sent_at":"2026-09-01T10:15:30.123Z","challenge":"8f14e45fceea167a5a36dedd4bea2543"}}}}},"responses":{"2XX":{"description":"The event was received."}}}}}}