22 endpoints. Send your API key as Authorization: Bearer <key> on each request; see The API and AI assistants for keys, errors, idempotency and the conventions every endpoint shares.
GET /api/coolify-notifications
Admins and owners. The one address to paste into Coolify (Notifications > Webhook), the project for other alerts, the Coolify project names that route an alert, and the projects to choose from.
The address is /ingest/{key}/coolify on this host, made from the ingest key of the project for other alerts, so it holds a secret. It is null until a project is chosen. Each Coolify notification is filed by the project name it carries - a name set below, else a project with the same name - and otherwise in the project for other alerts.
Responses:
| Status | Meaning |
|---|---|
| 200 | url, catchall_project, aliases [{name, project_id, project_name}], max_aliases, projects |
| 403 | Not an admin or owner |
PUT /api/coolify-notifications
Admins and owners. Choose the project for other alerts. The address changes, because it is made from that project's key.
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
project_id | integer | Yes |
Responses:
| Status | Meaning |
|---|---|
| 200 | The same answer as GET |
| 400 | Not a project of this organisation |
| 403 | Not an admin or owner |
PUT /api/coolify-notifications/names
Admins and owners. Alerts from the Coolify project with this name go to this AperioFlow project. Capital letters and extra spaces are ignored; setting a name again replaces it.
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Up to 200 characters. |
project_id | integer | Yes |
Responses:
| Status | Meaning |
|---|---|
| 200 | The same answer as GET |
| 400 | A bad name |
| 403 | Not an admin or owner |
| 409 | At most 100 names |
DELETE /api/coolify-notifications/names
Admins and owners. Remove a name.
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes |
Responses:
| Status | Meaning |
|---|---|
| 200 | The same answer as GET |
| 404 | That name is not set |
POST /api/coolify-notifications/test
Admins and owners. Send a harmless test notification (an info issue titled "Coolify: Test notification from AperioFlow") by the same route as a real one, and say where it landed.
Request body (application/json).
| Field | Type | Required | Description |
|---|---|---|---|
project | string | No | Optional. Pretend the alert comes from this Coolify project. Up to 200 characters. |
Responses:
| Status | Meaning |
|---|---|
| 202 | project {id, name}, routed_by ("name you set", "same name" or "project for other alerts") and the issue |
| 409 | Choose the project for other alerts first |
GET /api/issues
Issues across every project, most recently seen first (or by sort)
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
project_id | query | integer | No | Only issues in this project. From 1 to .... |
status | query | string | No | One status, or several separated by commas (open,ignored). |
level | query | string | No | One level, or several separated by commas (fatal,error). |
environment | query | string | No | Exact environment, such as production. |
platform | query | string | No | Exact platform, such as web. |
q | query | string | No | Case-insensitive text to find in the title, error type or route. |
since | query | string (date-time) | No | Only issues last seen at or after this time. |
sort | query | string | No | last_seen (default), first_seen or event_count, largest or newest first. One of: last_seen, first_seen, event_count. Default "last_seen". |
limit | query | integer | No | Default 100. From 1 to 500. |
offset | query | integer | No | Skip this many results (for paging). Default 0. From 0 to .... |
Responses:
| Status | Meaning |
|---|---|
| 200 | Issues, each with its project name and a summary of its latest event (array of IssueListItem) |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
PATCH /api/issues
Resolve, ignore or reopen several issues at once
All or nothing. If any id does not exist the request fails with a 404 and nothing changes.
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Actor | header | string | No | Name recorded in the activity log (up to 200 characters, URI-encoded if not ASCII). |
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
ids | array of integer | Yes | Up to 500 items. |
status | IssueStatus | Yes | One of: open, resolved, ignored. |
Example:
{
"ids": [
12,
15,
19
],
"status": "resolved"
}
Responses:
| Status | Meaning |
|---|---|
| 200 | The issues after the change |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
GET /api/issues/summary
Issue counts overall and per project
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
project_id | query | integer | No | Only count this project. From 1 to .... |
Responses:
| Status | Meaning |
|---|---|
| 200 | Counts |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
GET /api/projects/{id}/issues
Issues for a project, most recently seen first (or by sort)
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
status | query | string | No | One status, or several separated by commas (open,ignored). |
level | query | string | No | One level, or several separated by commas (fatal,error). |
environment | query | string | No | Exact environment, such as production. |
platform | query | string | No | Exact platform, such as web. |
q | query | string | No | Case-insensitive text to find in the title, error type or route. |
since | query | string (date-time) | No | Only issues last seen at or after this time. |
sort | query | string | No | last_seen (default), first_seen or event_count, largest or newest first. One of: last_seen, first_seen, event_count. Default "last_seen". |
limit | query | integer | No | Default 100. From 1 to 500. |
offset | query | integer | No | Skip this many results (for paging). Default 0. From 0 to .... |
Responses:
| Status | Meaning |
|---|---|
| 200 | Issues, each with a summary of its latest event (array of IssueListItem) |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
POST /api/projects/{id}/issues
Report one event, or an array of up to 100
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
X-Actor | header | string | No | Name recorded in the activity log (up to 200 characters, URI-encoded if not ASCII). |
Request body (application/json, required): IssueEventBatch
Responses:
| Status | Meaning |
|---|---|
| 202 | Events recorded |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
GET /api/projects/{id}/ingest-key
The project's current ingest key and the path to post events to
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
Responses:
| Status | Meaning |
|---|---|
| 200 | The key (IngestKey) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
POST /api/projects/{id}/ingest-key
Replace the project's ingest key (the old one stops working immediately)
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
Responses:
| Status | Meaning |
|---|---|
| 200 | The new key (IngestKey) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
GET /api/push
Whether push is configured, the VAPID public key and how many devices are subscribed
Responses:
| Status | Meaning |
|---|---|
| 200 | Push settings |
| 401 | Missing or invalid API key (Error) |
POST /api/push/subscriptions
Register a device (the browser's PushSubscription JSON); idempotent
Request body (application/json, required): PushSubscription.
| Field | Type | Required | Description |
|---|---|---|---|
endpoint | string (uri) | Yes | https URL from the browser push service. |
keys | object | Yes |
Responses:
| Status | Meaning |
|---|---|
| 201 | Subscribed |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 503 | Push is not configured on the server |
DELETE /api/push/subscriptions
Remove a device
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
endpoint | string | Yes |
Responses:
| Status | Meaning |
|---|---|
| 204 | Removed |
| 401 | Missing or invalid API key (Error) |
POST /api/push/test
Send a test notification to one subscribed device
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
endpoint | string | Yes |
Responses:
| Status | Meaning |
|---|---|
| 200 | Sent |
| 401 | Missing or invalid API key (Error) |
| 404 | The device is not subscribed |
| 502 | The push service rejected the notification |
GET /api/issues/{id}
An issue with its latest events (up to 50, newest first)
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
Responses:
| Status | Meaning |
|---|---|
| 200 | The issue (IssueDetail) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
PATCH /api/issues/{id}
Resolve, ignore or reopen an issue
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
X-Actor | header | string | No | Name recorded in the activity log (up to 200 characters, URI-encoded if not ASCII). |
Request body (application/json, required).
| Field | Type | Required | Description |
|---|---|---|---|
status | IssueStatus | No | One of: open, resolved, ignored. |
Responses:
| Status | Meaning |
|---|---|
| 200 | The updated issue (Issue) |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
DELETE /api/issues/{id}
Delete an issue and its events (it is recreated if the error happens again)
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
Responses:
| Status | Meaning |
|---|---|
| 204 | Deleted |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
GET /api/issues/{id}/events
An issue's stored events (the latest 50 are kept), newest first
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | From 1 to 2147483647. |
limit | query | integer | No | Default 50. From 1 to 50. |
before | query | integer | No | Return entries with an id lower than this (for paging). From 1 to .... |
Responses:
| Status | Meaning |
|---|---|
| 200 | Events, with full stack and context (array of IssueEvent) |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 401 | Missing or invalid API key (Error) |
| 404 | Item (or its parent) does not exist (Error) |
POST /ingest/{key}
Report events with a project ingest key (no API key)
For browsers and mobile apps. CORS is open, and any content type is parsed as JSON, so navigator.sendBeacon(url, JSON.stringify(event)) works. user_agent defaults to the request's User-Agent header. Limited to 300 events per minute per key.
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
key | path | string | Yes | The project's ingest_key. |
Request body (application/json, required): IssueEventBatch
Responses:
| Status | Meaning |
|---|---|
| 202 | Events recorded |
| 400 | The request body is invalid or is not valid JSON (Error) |
| 404 | Unknown ingest key (Error) |
| 429 | Rate limit reached. See the Retry-After header. (Error) |
POST /webhooks/gitguardian
GitGuardian custom webhook (signed, no API key)
GitGuardian posts its incident events here. The request must carry Timestamp and Gitguardian-Signature: sha256=<hex> (or the deprecated X-GitGuardian-Signature): an HMAC-SHA256 of the raw body keyed with the timestamp followed by a token from GITGUARDIAN_WEBHOOK_SECRET. Requests more than 5 minutes from the server's clock are refused. Each incident becomes one Security issue (fingerprint gitguardian:<incident id>) in the project whose repo_url matches the repository, or in the fallback project. The secret value is never stored. The GitGuardian test message gets a 200 and stores nothing. Limited to 120 requests per minute per client IP.
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Timestamp | header | string | Yes | |
Gitguardian-Signature | header | string | Yes |
Request body (application/json, required)
Responses:
| Status | Meaning |
|---|---|
| 200 | Test message |
| 202 | The incident's issue was created or updated |
| 400 | Body is not JSON or the incident has no id |
| 401 | Missing or invalid signature |
| 429 | Rate limit reached. See the Retry-After header. |
| 503 | GITGUARDIAN_WEBHOOK_SECRET is not set |