Errors and responses
Success
A successful response wraps the result in data. Lists add pagination.
json
{
"data": [ { "id": "…", "slug": "spring", "shortLink": "https://rvlnk.link/spring" } ],
"pagination": { "page": 1, "limit": 50, "total": 1 }
}
Errors
Errors come with a matching HTTP status and always have this shape:
json
{
"error": {
"code": "conflict",
"message": "This slug is already taken."
}
}
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_request | The request is wrong. message says what. |
| 401 | unauthorized | No key, or an invalid or expired key. |
| 403 | forbidden | The key lacks a permission (error.requiredPermission), or the role of the key's owner cannot do this. |
| 403 | license_limit_reached | A limit of the plan is reached. error.licenseLimitReached is true. error.licenseExpired is true when the plan has expired. |
| 404 | not_found | No such item in this workspace. |
| 409 | conflict | Already exists, for example a taken slug or tag name. |
| 429 | rate_limited | More than 300 requests a minute for the key. See Retry-After. |
| 5xx | internal_error | Something went wrong on our side. |
Bulk requests
Bulk create, update and delete return HTTP 200 and report each item separately. One failed item does not stop the others. A failed item has error and a code (the same codes as above), plus index (position in the request array, for create) or id (for update and delete).
json
{
"data": {
"created": [ { "id": "…", "slug": "a1", "shortLink": "https://rvlnk.link/a1" } ],
"failed": [ { "index": 1, "error": "This slug is already taken.", "code": "conflict" } ]
}
}
Pagination
GET /links takes page (default 1) and limit (default 50, maximum 200).