Webhooks
Register endpoints, manage them, and inspect delivery attempts for payment events.
Newest first, as { data, total, take, skip } with take up to 100 (default 100), without signing secrets. destinationBlocked marks an endpoint this service disabled because its host stopped resolving to a public address.
Requires the webhooks:read scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
take?numberPage size: how many items to return (1 to 100).
value <= 100100skip?numberHow many items to skip before this page (offset).
0OK
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X GET 'https://api.cosmospay.lat/cosmos-api/v1/webhooks'{ "data": [ { "id": "we_9z8a1b0000abcd1234efgh", "url": "https://integrator.example.com/webhooks/cosmos", "description": "Production payment events", "enabled": true, "destinationBlocked": false, "eventTypes": [ "PAYMENT_INTENT_SUCCEEDED" ], "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:56.000Z" } ], "total": 1, "take": 100, "skip": 0}url must be https, carry no credentials and resolve to a public address (loopback, private, link-local and cloud metadata hosts are 400 validation_failed). secret (whsec_...) is returned only here and on rotation: every delivery is signed with it in the signature header (x-cosmos-signature by default) as t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>">. An empty or omitted eventTypes receives every event type.
Requires the webhooks:write scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
application/json- body
A webhook endpoint to register: an https URL that receives signed event notifications.
url*stringHTTPS URL that will receive POSTed event notifications.
description?stringFree-text label for the endpoint (at most 255 characters).
eventTypes?array<>Event types to subscribe to. Omit/empty to receive all events.
Created
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X POST 'https://api.cosmospay.lat/cosmos-api/v1/webhooks' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://integrator.example.com/webhooks/cosmos"}'{ "id": "we_9z8a1b0000abcd1234efgh", "url": "https://integrator.example.com/webhooks/cosmos", "description": "Production payment events", "enabled": true, "destinationBlocked": false, "eventTypes": [ "PAYMENT_INTENT_SUCCEEDED" ], "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:56.000Z", "secret": "whsec_3f9a1c…"}The endpoint without its signing secret, which only the create and rotate-secret routes return.
Requires the webhooks:read scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringOK
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X GET 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string'{ "id": "we_9z8a1b0000abcd1234efgh", "url": "https://integrator.example.com/webhooks/cosmos", "description": "Production payment events", "enabled": true, "destinationBlocked": false, "eventTypes": [ "PAYMENT_INTENT_SUCCEEDED" ], "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:56.000Z"}Changes only the fields sent. A new url is checked as on create, enabled: true checks the stored one again, and either clears destinationBlocked. eventTypes replaces the filter (an empty list receives every event type).
Requires the webhooks:write scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringapplication/json- body
Changes to a webhook endpoint; only the fields sent change.
url?stringNew https URL for deliveries, checked as on create.
description?stringFree-text label for the endpoint (at most 255 characters).
enabled?booleanPause/resume deliveries to this endpoint.
eventTypes?array<>Event types to subscribe to; replaces the current filter. An empty list receives every event type.
OK
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X PATCH 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "we_9z8a1b0000abcd1234efgh", "url": "https://integrator.example.com/webhooks/cosmos", "description": "Production payment events", "enabled": true, "destinationBlocked": false, "eventTypes": [ "PAYMENT_INTENT_SUCCEEDED" ], "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:56.000Z"}Deletes the endpoint together with its delivery history; nothing more is sent to it.
Requires the webhooks:write scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringOK
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X DELETE 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string'{ "id": "we_9z8a1b0000abcd1234efgh", "deleted": true}Replaces secret at once and returns the new one, shown only here. Every delivery sent from now on is signed with the new secret only: the old one has no grace period.
Requires the webhooks:write scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringCreated
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X POST 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string/rotate-secret'{ "id": "we_9z8a1b0000abcd1234efgh", "url": "https://integrator.example.com/webhooks/cosmos", "description": "Production payment events", "enabled": true, "destinationBlocked": false, "eventTypes": [ "PAYMENT_INTENT_SUCCEEDED" ], "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:56.000Z", "secret": "whsec_3f9a1c…"}POSTs one signed ping event (not stored as a delivery) to the endpoint, enabled or not, and answers whether it replied 2xx (ok, responseStatus, error). A URL that no longer resolves to a public address disables the endpoint and marks it destinationBlocked.
Requires the webhooks:write scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringCreated
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
The budget in x-cosmos-rate-limit is spent for this caller. Honour Retry-After.
The ratelimit-* triple rides along on successful responses too, so a client can pace itself instead of being refused. If the counter store itself is unreachable the guard fails closed and answers 503 provider_unavailable.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X POST 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string/ping'{ "ok": true, "responseStatus": 200, "error": null}Newest first, as { data, total, take, skip } with take up to 100 (default 20), narrowed by status when given. Each delivery reports its eventType, eventId, attempts, last responseStatus and error; the event body that was sent is never returned.
Requires the webhooks:read scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringstatus?stringOnly deliveries in this status. Omit for every status.
"PENDING""SUCCEEDED""FAILED""RETRYING"take?numberPage size: how many items to return (1 to 100).
value <= 10020skip?numberHow many items to skip before this page (offset).
0OK
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X GET 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string/deliveries'{ "data": [ { "id": "wd_9z8a1b0000abcd1234efgh", "endpointId": "we_9z8a1b0000abcd1234efgh", "eventType": "PAYMENT_INTENT_SUCCEEDED", "eventId": "evt_2c3d4e5f-aaaa-bbbb-cccc-1234567890ab", "status": "SUCCEEDED", "attempts": 1, "responseStatus": 200, "error": null, "lastAttemptAt": "2026-06-21T12:34:57.000Z", "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:57.000Z" } ], "total": 1, "take": 20, "skip": 0}Re-sends the stored body with the same event id, signed again with the endpoint's current secret, retrying with backoff inside this request until a 2xx or the attempts run out, and answers the updated delivery (without its body). A delivery past its payload retention window is 409 payload_expired.
Requires the webhooks:write scope.
apiKeyAuthorizationBearer <API key>Your Cosmos Pay secret API key, sent as Authorization: Bearer <apiKey>.
id*stringdeliveryId*stringCreated
The body, query or path failed validation. message is an array of the individual failures.
Routes that reject a valid request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
no_authenticated_consumer: The gateway forwarded no API key identity
insufficient_scope: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked x-cosmos-public-key, with a message saying so; more scopes will not help, the key is the wrong one.
gateway_required: the request did not arrive through APISIX.
No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
payload_expired: the delivery is past its retention window. The event body was cleared, so there is nothing left to re-send; the delivery row itself stays as an audit record.
The budget in x-cosmos-rate-limit is spent for this caller. Honour Retry-After.
The ratelimit-* triple rides along on successful responses too, so a client can pace itself instead of being refused. If the counter store itself is unreachable the guard fails closed and answers 503 provider_unavailable.
Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
curl -X POST 'https://api.cosmospay.lat/cosmos-api/v1/webhooks/string/deliveries/string/redeliver'{ "id": "wd_9z8a1b0000abcd1234efgh", "endpointId": "we_9z8a1b0000abcd1234efgh", "eventType": "PAYMENT_INTENT_SUCCEEDED", "eventId": "evt_2c3d4e5f-aaaa-bbbb-cccc-1234567890ab", "status": "SUCCEEDED", "attempts": 1, "responseStatus": 200, "error": null, "lastAttemptAt": "2026-06-21T12:34:57.000Z", "createdAt": "2026-06-21T12:34:56.000Z", "updatedAt": "2026-06-21T12:34:57.000Z"}