Documentation Index
Fetch the complete documentation index at: https://dev.magicpost.in/llms.txt
Use this file to discover all available pages before exploring further.
Every error from /api/v1/* returns a JSON body with at minimum an error field (a human-readable message) and an error_type field (a machine-readable code):
{
"error": "Human-readable message",
"error_type": "token_expired"
}
Some errors carry additional fields:
actionable: true — you can fix the cause yourself. Always paired with a hint.
hint — the exact message to surface in your UI or LLM conversation (e.g. "Tell the user to reconnect LinkedIn from MagicPost > Settings").
existing — present on schedule warnings; an array of posts already on the same day or in the same slot.
Error type catalog
error_type | HTTP | Description |
|---|
auth_required | 401 | No Bearer token provided, or token does not start with mp_. |
auth_unavailable | 503 | Auth service is degraded (e.g. a Supabase outage). Transient — retry with backoff. |
user_not_found | 401 | Token shape is valid but the token is unknown or has been revoked. |
rate_limited | 429 | Too many requests in the current one-minute window. See Rate limits. |
missing_data | 400 | A required input field is absent (e.g. at_iso for schedule). |
empty_content | 400 | Post content is empty or whitespace only. |
post_not_found | 404 | Post does not exist or is owned by a different user. Both cases surface as 404 to avoid leaking ownership. |
token_expired | 400 | Your LinkedIn OAuth token (not your MagicPost PAT) has expired. actionable: true — the user must reconnect LinkedIn. |
failed_tag | 400 | One or more @mentions in the post cannot be tagged due to the target’s LinkedIn privacy settings. |
too_late | 400 | Attempting to schedule more than six months in the future. |
already_published | 409 | Attempting to cancel-schedule or republish a post that has already gone out. |
db_error | 500 | Internal database issue. No details are exposed in the response — retry with backoff. |
unknown_error | 500 | An unanticipated error. Retrying with backoff may help; contact support if it persists. |
network_error | (varies) | The MCP server could not reach the MagicPost API. Surfaced by the MCP tool layer, not the API itself. |
Schedule warnings
Schedule warnings are returned as HTTP 200 with success: false. They are informational signals, not failures — the request was understood, but MagicPost detected a potential scheduling conflict.
warning | When it appears |
|---|
same_day_posts | At least one other post is already scheduled on the same day in your timezone. |
exact_slot_conflict | Another post is scheduled within ±5 minutes of the target slot (a stronger signal). |
To proceed despite a warning, re-send the request with confirm_same_day: false (and/or confirm_exact_slot: false).
Rate limits
Rate limits are applied per PAT, per minute, in a fixed window:
| Class | Limit | Applies to |
|---|
| Default | 60 req / min | All endpoints by default |
| Expensive | 5 req / min | /api/v1/refresh-posts (makes a live call to LinkedIn) |
When you exceed the limit, the API returns HTTP 429:
{
"error": "Rate limit exceeded (60 req/min for this endpoint class)",
"error_type": "rate_limited",
"current_count": 61,
"limit": 60,
"hint": "Wait until the start of the next minute and retry."
}
The window resets at the start of every wall-clock minute.
Retry policy
| Error | Retry? | Strategy |
|---|
network_error | Yes | Exponential backoff, up to 2 retries. |
5xx (db_error, unknown_error, auth_unavailable) | Yes | Exponential backoff. |
rate_limited | Yes | Wait until the start of the next minute, then retry. |
| 4xx (all others) | No | The request itself is wrong — retrying will not help. |
The MCP server implements this retry policy internally. Your tools see only the final outcome after retries are exhausted.