Error Handling
All errors follow a consistent JSON format.
Error format
{
"error": {
"code": "validation_error",
"message": "text is required",
"field": "text",
"docs": "https://docs.pepe.business/errors#validation_error"
},
"requestId": "req_xxx"
}
HTTP codes
| Code | Meaning |
|---|---|
| 400 | Invalid request (validation) |
| 401 | Unauthenticated |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 409 | Conflict (duplicate slug) |
| 422 | Unprocessable entity |
| 429 | Rate limit exceeded |
| 500 | pepe server error |
| 502 | Underlying platform error (Twitter, etc.) |
| 503 | Service unavailable |
Error codes
| Code | Cause |
|---|---|
validation_error | Invalid or missing field |
unauthorized | Missing or invalid API key |
forbidden | Insufficient scope |
not_found | Nonexistent resource |
rate_limit_exceeded | Too many requests |
platform_error | Error on the social network side |
media_too_large | File exceeding the limit |
account_disconnected | The OAuth account has expired |
duplicate_slug | Slug already used |
webhook_failed | Webhook delivery failed |
Automatic retry
5xx and 429 errors can be retried. 4xx errors must never be retried (client-side error).
Idempotency
For sensitive POST/PATCH, add an Idempotency-Key header:
POST /v1/posts
Idempotency-Key: my-unique-key-123
{...}
If the same key is used twice, the second request returns the response of the first without recreating the resource. Useful for retries without risk of duplication.
Logging
Always log the requestId to facilitate support:
try {
await pepe.posts.create({...});
} catch (err) {
console.error(`[req:${err.requestId}] pepe error: ${err.code}`);
}