Cosmoner Docs
API Reference

Webhooks

Subscriptions to platform events. Each endpoint has a signing secret, returned once when it is created or rotated, that signs every delivery so you can verify it came from us. Repeated failures pause an endpoint automatically; resuming it re-queues what was held.

GET
/v1/projects/{projectId}/webhooks

Every endpoint on the project, newest first.

Auth: a project API key carrying webhooks:read.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/projects/string/webhooks"
{  "success": true,  "data": [    {      "id": "string",      "name": "string",      "description": "string",      "url": "http://example.com",      "events": [        "email.sent"      ],      "enabled": true,      "secretHint": "string",      "consecutiveFailures": -9007199254740991,      "disabledAt": "2019-08-24T14:15:22Z",      "disabledReason": "MANUAL",      "lastSuccessAt": "2019-08-24T14:15:22Z",      "lastFailureAt": "2019-08-24T14:15:22Z",      "createdAt": "2019-08-24T14:15:22Z",      "updatedAt": "2019-08-24T14:15:22Z"    }  ]}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
POST
/v1/projects/{projectId}/webhooks

Subscribes a URL to one or more events.

The signing secret is returned in this response and nowhere else. Use it to verify that a delivery came from us; if you lose it, rotate it rather than trying to read it back.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/projects/string/webhooks" \  -H "Content-Type: application/json" \  -d '{    "name": "string",    "url": "http://example.com",    "events": [      "email.sent"    ]  }'
{  "success": true,  "data": {    "id": "string",    "name": "string",    "description": "string",    "url": "http://example.com",    "events": [      "email.sent"    ],    "enabled": true,    "secretHint": "string",    "consecutiveFailures": -9007199254740991,    "disabledAt": "2019-08-24T14:15:22Z",    "disabledReason": "MANUAL",    "lastSuccessAt": "2019-08-24T14:15:22Z",    "lastFailureAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z",    "secret": "string"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
GET
/v1/projects/{projectId}/webhooks/{endpointId}

The endpoint, with a count of its deliveries by status.

Auth: a project API key carrying webhooks:read.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/projects/string/webhooks/string"
{  "success": true,  "data": {    "endpoint": {      "id": "string",      "name": "string",      "description": "string",      "url": "http://example.com",      "events": [        "email.sent"      ],      "enabled": true,      "secretHint": "string",      "consecutiveFailures": -9007199254740991,      "disabledAt": "2019-08-24T14:15:22Z",      "disabledReason": "MANUAL",      "lastSuccessAt": "2019-08-24T14:15:22Z",      "lastFailureAt": "2019-08-24T14:15:22Z",      "createdAt": "2019-08-24T14:15:22Z",      "updatedAt": "2019-08-24T14:15:22Z"    },    "stats": {      "succeeded": -9007199254740991,      "failed": -9007199254740991,      "pending": -9007199254740991    }  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
PATCH
/v1/projects/{projectId}/webhooks/{endpointId}

Changes the name, description, URL, subscribed events, or whether the endpoint is enabled.

Switching a disabled endpoint back on also clears its failure streak — otherwise the next single failure would pause it again.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X PATCH "https://example.com/v1/projects/string/webhooks/string" \  -H "Content-Type: application/json" \  -d '{}'
{  "success": true,  "data": {    "id": "string",    "name": "string",    "description": "string",    "url": "http://example.com",    "events": [      "email.sent"    ],    "enabled": true,    "secretHint": "string",    "consecutiveFailures": -9007199254740991,    "disabledAt": "2019-08-24T14:15:22Z",    "disabledReason": "MANUAL",    "lastSuccessAt": "2019-08-24T14:15:22Z",    "lastFailureAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
DELETE
/v1/projects/{projectId}/webhooks/{endpointId}

Deletes the endpoint and its delivery history.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X DELETE "https://example.com/v1/projects/string/webhooks/string"
{  "success": true,  "data": null}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
GET
/v1/projects/{projectId}/webhooks/{endpointId}/deliveries

The endpoint's delivery log, newest first, with what the endpoint answered on each attempt.

Paginated by cursor: pass the nextCursor from one response as cursor on the next. A nextCursor of null means there are no further pages. Narrow the log with status and eventType.

Auth: a project API key carrying webhooks:read.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Query Parameters

status?string

Value in

  • "PENDING"
  • "SUCCEEDED"
  • "FAILED"
eventType?string

Value in

  • "email.sent"
  • "email.delivered"
  • "email.delivery_delayed"
  • "email.bounced"
  • "email.complained"
  • "email.opened"
  • "email.clicked"
  • "email.rejected"
  • "email.rendering_failed"
  • "app.deployed"
  • "app.failed"
limit?integer
Range1 <= value <= 100
Default25
cursor?string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/projects/string/webhooks/string/deliveries"
{  "success": true,  "data": {    "deliveries": [      {        "id": "string",        "eventType": "email.sent",        "eventId": "string",        "payload": {          "property1": null,          "property2": null        },        "status": "PENDING",        "attempt": -9007199254740991,        "nextAttemptAt": "2019-08-24T14:15:22Z",        "responseStatus": -9007199254740991,        "responseBody": "string",        "errorMessage": "string",        "durationMs": -9007199254740991,        "deliveredAt": "2019-08-24T14:15:22Z",        "createdAt": "2019-08-24T14:15:22Z"      }    ],    "nextCursor": "string"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
POST
/v1/projects/{projectId}/webhooks/{endpointId}/deliveries/{deliveryId}/replay

Queues the same event for delivery again, as a new attempt with its own row. The original delivery is left as it was.

The endpoint must be enabled — replaying into a paused endpoint returns 400.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length
deliveryId*string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/projects/string/webhooks/string/deliveries/string/replay"
{  "success": true,  "data": {    "id": "string",    "eventType": "email.sent",    "eventId": "string",    "payload": {      "property1": null,      "property2": null    },    "status": "PENDING",    "attempt": -9007199254740991,    "nextAttemptAt": "2019-08-24T14:15:22Z",    "responseStatus": -9007199254740991,    "responseBody": "string",    "errorMessage": "string",    "durationMs": -9007199254740991,    "deliveredAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
POST
/v1/projects/{projectId}/webhooks/{endpointId}/resume

Clears an automatic pause and re-queues the events held while the endpoint was down.

An endpoint is paused automatically after enough consecutive failures; resuming resets that streak.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/projects/string/webhooks/string/resume"
{  "success": true,  "data": {    "id": "string",    "name": "string",    "description": "string",    "url": "http://example.com",    "events": [      "email.sent"    ],    "enabled": true,    "secretHint": "string",    "consecutiveFailures": -9007199254740991,    "disabledAt": "2019-08-24T14:15:22Z",    "disabledReason": "MANUAL",    "lastSuccessAt": "2019-08-24T14:15:22Z",    "lastFailureAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
POST
/v1/projects/{projectId}/webhooks/{endpointId}/rotate-secret

Issues a new signing secret and returns it once. The previous secret stops verifying immediately, so deploy the new one before rotating if you cannot tolerate a gap.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/projects/string/webhooks/string/rotate-secret"
{  "success": true,  "data": {    "id": "string",    "secret": "string"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
POST
/v1/projects/{projectId}/webhooks/{endpointId}/test

Fires a synthetic event at the endpoint immediately and returns what it answered, so a misconfigured URL is caught at setup rather than on the first real event.

A test never moves the failure streak in either direction: an unreachable endpoint is what you are checking for, and a test that succeeds says nothing about real events still failing.

Auth: a project API key carrying all of webhooks:read and webhooks:write.

AuthorizationBearer <token>

A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.

In: header

Path Parameters

projectId*string
Length1 <= length
endpointId*string
Length1 <= length

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/projects/string/webhooks/string/test" \  -H "Content-Type: application/json" \  -d '{}'
{  "success": true,  "data": {    "outcome": "PENDING",    "delivery": {      "id": "string",      "eventType": "email.sent",      "eventId": "string",      "payload": {        "property1": null,        "property2": null      },      "status": "PENDING",      "attempt": -9007199254740991,      "nextAttemptAt": "2019-08-24T14:15:22Z",      "responseStatus": -9007199254740991,      "responseBody": "string",      "errorMessage": "string",      "durationMs": -9007199254740991,      "deliveredAt": "2019-08-24T14:15:22Z",      "createdAt": "2019-08-24T14:15:22Z"    }  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}
{  "success": false,  "error": {    "code": "string",    "message": "string",    "details": {      "property1": null,      "property2": null    },    "issues": null,    "docsUrl": "http://example.com"  }}

Integrations

Connections to the services a project builds from and pulls images from: GitHub, GitLab and Bitbucket for source code, and Docker Hub and the GitHub container registry for container images. A connection belongs to one project — connecting an account in one project never makes it available in another — and the credentials behind it are stored encrypted and never returned. Connecting is done in the control panel, through each service's own authorization page, or for Docker Hub by entering an access token (a read-only one is enough to deploy). The calls here report on a connection, read what it can see — repositories, branches, configuration files, images and tags — and remove it. A GitHub connection is made of accounts. The project links the Cosmoner GitHub App's installation on each GitHub account or organization that granted it access, and can link several; each grants read access to the repositories chosen on GitHub, and those with the Packages read permission to their container images too. Uninstalling the app on GitHub detaches that account from every project that linked it. While a git service is connected, a push to the branch an app deploys from redeploys the app, as long as its auto-deploy is on. Nothing needs to be called for this. Listing GitHub repositories and browsing a repository's directories are available in the control panel.

Support tickets

Conversations with the support team. A ticket belongs to one project, and an API key reaches only the tickets of the project it was issued for. Each ticket carries its whole conversation as a timeline of events, oldest first; when support replies, the ticket moves to `PENDING` and the member who opened it is emailed. Your own reply moves it back to `OPEN`.

On this page