| Status | Meaning |
|---|---|
200 OK, 201 Created, 204 No Content |
Success |
400 Bad Request |
The request conflicts with existing data, e.g. a duplicate webhook URL |
401 Unauthorized |
The token is missing, invalid, expired or revoked |
403 Forbidden |
The token is valid, but not allowed to do this |
404 Not Found |
The resource does not exist, was deleted, or belongs to another organization |
422 Unprocessable Entity |
The request body or path failed validation |
429 Too Many Requests |
Rate limit exceeded |
500 Internal Server Error |
Something went wrong on our side. Retry with backoff. |
The API uses three error shapes, depending on where the error comes from. Always check the HTTP status first, then read code or error.
{
"message": "Insufficient scope",
"code": "insufficient_scope"
}
code can be missing for generic errors. Some errors add a value object with details.
{
"error": "validation_error",
"details": [
{
"code": "custom",
"message": "Target URL must use HTTPS",
"path": ["targetUrl"]
}
]
}
details lists each problem with the path of the offending field. Not-found errors have only error, e.g. {"error": "webhook_not_found"}.
/oauth/* endpoints use the standard OAuth format, {"error": "...", "error_description": "..."}. See Authentication for the codes.
| Status | code / error |
What it means and what to do |
|---|---|---|
| 401 | (no code) | No Authorization: Bearer header. Add it. |
| 401 | invalid_token |
Unknown, expired or revoked token. Refresh an OAuth token, or create a new PAT. |
| 403 | insufficient_scope |
The token lacks the scope this endpoint needs. Create a token with it, or ask the user to re-authorize with it. |
| 403 | insufficient-permissions |
The user behind the token lacks the role, e.g. a non-owner trying to change webhooks. |
| 403 | limit-exceeded |
The organization's plan does not include API access. Upgrade the plan. |
| 403 | account-not-active |
The user behind the token is deactivated. |
| 403 | account-deletion-pending |
The user behind the token is being deleted. |
| 400 | webhook-duplicate-url |
Another webhook in the organization uses this URL. |
| 404 | webhook_not_found |
No active webhook with this UUID in your organization. |
| 404 | user_not_found |
The user behind the token no longer exists. |
| 404 | not-found |
The organization the token belongs to is not accessible. |
| 422 | validation_error |
Fix the fields listed in details. |
| 429 | rate-limit-exceeded |
Slow down. See below. |
| Endpoints | Limit |
|---|---|
/api/v1/* |
50 requests per 10 seconds, per client IP address |
/oauth/* |
1,000 requests per 10 seconds, per client IP address |
Limits count per IP address, not per token. Several integrations behind one IP share the budget.
Every response carries the current state of your budget:
| Header | Meaning |
|---|---|
RateLimit-Limit |
Requests allowed in the window |
RateLimit-Remaining |
Requests left in the current window |
RateLimit-Reset |
Seconds until the window resets |
When you go over, you get 429 with a Retry-After header (in seconds) and this body: