Webhooks
8 endpoints in this family.
List your webhook subscriptions
GET/api/v1/webhooks
Key role admin or above
Returns where Coplace calls you and for which events, plus the list of every event name you can subscribe to. Secrets are never returned.
Response
The subscriptions, the event catalogue and the latest deliveries.
data.eventsstring[]Every event name you can subscribe to.
data.subscriptionsWebhookSubscription[]Your subscriptions, newest first.
data.deliveriesWebhookDelivery[]The 50 most recent deliveries. The full log is
GET /webhooks/deliveries.
curl https://coplace.io/api/v1/webhooks \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "events": [ "…" ], "subscriptions": [ {} ], "deliveries": [ {} ] }}Subscribe to events
POST/api/v1/webhooks
Key role admin or above
Registers an HTTPS address that Coplace calls when something happens. Without this your software has to poll, which is slower and heavier for both of us.
The response carries the signing secret once and never again: store it now. Each call is signed with it, and is retried up to six times with growing delays (1 min, 5 min, 30 min, 2 h, 12 h).
Body
urlstringrequiredWhere to call. Must start with https://.
eventsstring[]requiredWhich events to receive.
*means all of them.labelstringA name for you, shown in Coplace.
Response
The subscription id and its signing secret — shown only here.
data.idstringThe subscription id.
data.secretstringThe signing secret,
whsec_…. Shown only here.
Refusals
- 422
webhook_url_not_httpsThe address must start with https://. - 422
invalid_requestNo event, or an unknown event name.
curl -X POST https://coplace.io/api/v1/webhooks \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "…", "events": [ "…" ] }'{ "data": { "id": "…", "secret": "…" }}Unsubscribe
DEL/api/v1/webhooks/{id}
Key role admin or above
Removes the subscription. Nothing more is delivered to that address.
Path parameters
idstringThe subscription id.
Response
Confirmation that it is gone.
data.okbooleanAlways
true.
curl -X DELETE https://coplace.io/api/v1/webhooks/<id> \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "ok": true }}Change a subscription
PATCH/api/v1/webhooks/{id}
Key role admin or above
Moves the address, changes the events, renames, or pauses the subscription. Send only the fields you change. The secret does not change — rotate it with POST /webhooks/{id}/rotate-secret.
Path parameters
idstringThe subscription id.
Body
urlstringA new https address.
eventsstring[]The events to receive from now on.
*means all of them.labelstringA name for you, shown in Coplace.
isActivebooleanFalse pauses delivery without losing the subscription.
Response
The subscription, updated.
data.idstringThe subscription id.
data.urlstringThe https address called.
data.eventsstring[]The events delivered;
*means all.data.labelstringIts name.
data.isActivebooleanA paused subscription receives nothing.
data.lastDeliveredAtstringThe last successful call, ISO 8601, or
null.data.lastErrorstringWhat went wrong last time, or
null.data.previousSecretValidUntilstringDuring a rotation: until when the old secret still signs.
nullotherwise.data.createdAtstringISO 8601.
Refusals
- 422
webhook_url_not_httpsThe address must start with https://. - 422
invalid_requestNothing to change, an unknown event, or a field of the wrong type.
curl -X PATCH https://coplace.io/api/v1/webhooks/<id> \ -H "Authorization: Bearer $COPLACE_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "…", "events": [ "…" ] }'{ "data": { "id": "…", "url": "…", "events": [ "…" ], "label": "…", "isActive": true, "lastDeliveredAt": "…", "lastError": "…", "previousSecretValidUntil": "…", "createdAt": "…" }}Rotate the signing secret
POST/api/v1/webhooks/{id}/rotate-secret
Key role admin or above
Issues a new signing secret, returned once. For the next 24 hours every call carries two signatures — v1= with the new secret, then v1= with the old one — so you can deploy the new secret without missing a call. Accept a call when any v1 matches.
Rotating twice in a row forgets the oldest secret straight away.
Path parameters
idstringThe subscription id.
Response
The new secret, and until when the old one still signs.
data.secretstringThe new signing secret,
whsec_…. Shown only here.data.previousValidUntilstringISO date until which the old secret still signs.
curl -X POST https://coplace.io/api/v1/webhooks/<id>/rotate-secret \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "secret": "…", "previousValidUntil": "…" }}Send a test call
POST/api/v1/webhooks/{id}/test
Key role admin or above
Fires one signed call at your address right now and reports what came back: status code, round trip, and the error if there was one. Use it to prove your endpoint and your signature check before going live.
Path parameters
idstringThe subscription id.
Response
What your endpoint answered: status, duration, and any error.
data.okbooleanWhether it answered 2xx.
data.statusintegerThe HTTP status, or
nullwhen unreachable.data.msintegerThe round trip.
data.errorstringWhat went wrong, or
null.
curl -X POST https://coplace.io/api/v1/webhooks/<id>/test \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "ok": true, "status": 0, "ms": 0, "error": "…" }}List deliveries
GET/api/v1/webhooks/deliveries
Key role admin or above
Every call Coplace made — or is about to make — to your addresses: which event, how many attempts, what your server answered, and when the next attempt is due. Newest first.
This is what settles "we never received it": a failed delivery with lastError tells you what your endpoint said; no delivery at all means the event did not happen.
Query parameters
subscriptionIdstringOnly this subscription.
statusstringOnly deliveries in this state.
pendingdeliveredfailedeventstringOnly this event, e.g.
message.received.limitintegerPage size, 1 to 100. Default 50.
cursorstringThe
nextCursorof the previous page.
Response
A page of deliveries, newest first.
data.itemsWebhookDelivery[]The deliveries.
data.nextCursorstringPass it as
cursorfor the next page;nullat the end.data.hasMorebooleanWhether another page exists.
curl https://coplace.io/api/v1/webhooks/deliveries \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "items": [ {} ], "nextCursor": "…", "hasMore": true }}Redeliver an event
POST/api/v1/webhooks/deliveries/{id}/redeliver
Key role admin or above
Queues the same event again for the same subscription — typically after your endpoint was down and the delivery ended failed. It goes out within a minute, with fresh retries.
The payload is identical, including its id: if you already processed it, your deduplication on id will skip it.
Path parameters
idstringThe delivery id.
Response
The new delivery, pending.
data.idstringThe delivery id, also sent as
X-Coplace-Delivery.data.subscriptionIdstringThe subscription.
data.eventstringThe event name.
data.eventIdstringThe event's own id (
evt_…), the same across redeliveries: deduplicate on it.data.statusstringfailedafter six attempts.pendingdeliveredfaileddata.attemptsintegerAttempts so far.
data.responseStatusintegerThe HTTP status your server answered, or
null.data.lastErrorstringWhat went wrong, or
null.data.nextAttemptAtstringWhen the next attempt is due, for a pending delivery.
data.createdAtstringISO 8601.
data.deliveredAtstringISO 8601, or
null.
Refusals
- 404
not_foundNo such delivery in this workspace, or its subscription is paused or gone.
curl -X POST https://coplace.io/api/v1/webhooks/deliveries/<id>/redeliver \ -H "Authorization: Bearer $COPLACE_KEY"{ "data": { "id": "…", "subscriptionId": "…", "event": "…", "eventId": "…", "status": "pending", "attempts": 0, "responseStatus": 0, "lastError": "…", "nextAttemptAt": "…", "createdAt": "…", "deliveredAt": "…" }}