Errors
Mixpost returns conventional HTTP status codes, and every error body is JSON with at least a
message key.
Error format
All errors share the same envelope:
{
"message": "Unauthenticated."
}
Validation errors (422) add an errors object keyed by field name:
{
"message": "The name field is required. (and 1 more error)",
"errors": {
"name": ["The name field is required."],
"hex_color": ["The hex code is not valid"]
}
}
The top-level message on a 422 is Laravel's summary of the first error, not a fixed string.
Match on the errors keys rather than on message.
Status codes
| Code | Meaning |
|---|---|
200 | Success. |
201 | Created. See which endpoints return 201. |
401 | The bearer token is missing, malformed, unknown or expired. |
403 | The token is valid, but the user may not perform this action. See Permissions. |
404 | The workspace or the record does not exist. |
422 | The request body failed validation. |
500 | Unhandled server error. |
Created responses
Most successful calls return 200. These five return 201:
POST /{workspace}/tagsPOST /panel/workspacesPOST /panel/workspaces/{workspace}/subscriptionPOST /panel/usersPOST /panel/receipts
If you check for an exact 200, these will look like failures. Treat any 2xx as success.
401 Unauthenticated
{
"message": "Unauthenticated."
}
Returned when Authorization: Bearer <token> is absent, the token does not match a stored token, or
the token's expiry has passed. Tokens are matched by hash, so a token that was revoked in the
dashboard fails the same way as one that never existed.
403 Access forbidden
{
"message": "Access forbidden."
}
The token authenticated successfully, but the user behind it is not permitted. This is returned when
the user is not a member of the workspace in the URL, when their workspace role is too low for the
route, or — on /panel endpoints — when the user is not a platform admin.
On Mixpost Enterprise, a workspace whose plan has the API feature turned off is also refused with a
403, with a message describing the disabled feature rather than the text above. This does not apply
to Mixpost Pro, where the API is not gated per plan.
404 Not found
An unknown workspace UUID returns:
{
"message": "Workspace not found."
}
A workspace segment that is not a UUID at all matches no route, so it returns 404
body instead, before authentication runs.
An unknown record on a workspace endpoint returns the model name:
{
"message": "Post not found."
}
The message follows the model — Post not found., Tag not found., Media not found.,
Account not found.
The /panel/* endpoints (Workspaces, Subscriptions, Users, Receipts) do not produce these
friendly messages. Mixpost Enterprise registers no exception handler for them, so a missing record
returns Laravel's default 404 body instead. Rely on the status code, not the message.
422 Validation failed
{
"message": "The name field is required.",
"errors": {
"name": ["The name field is required."]
}
}
Media endpoints have one extra 422 case worth handling: when a workspace has hit a plan limit, the
body carries an additional top-level limit object alongside errors.limit.
500 Server error
{
"message": "Server Error"
}
When your instance runs with APP_DEBUG=true, this body also includes exception, file, line
and trace. Never run a production instance with debug enabled.
Rate limiting
Mixpost does not rate limit the API. No throttle is applied to any API route by the package itself.
However, Mixpost's API routes run inside your host Laravel application's api middleware group, and
that group is yours to configure. Laravel 8–10 skeletons include throttle:api (60 requests per
minute) in that group by default; Laravel 11 and newer do not, unless the application opts in via
->throttleApi().
So whether you ever receive a 429 — and at what threshold — depends entirely on the application
hosting Mixpost. If throttling is enabled there, responses carry the standard Retry-After and
X-RateLimit-* headers. Treat 429 as possible and back off on it, but don't assume a fixed budget.
Permissions
A token carries the full authority of the user who created it — there are no per-token scopes. What an endpoint allows is decided by that user's role in the workspace.
ADMIN and MEMBER have identical access across the API; no endpoint distinguishes them. The only
meaningful distinction is VIEWER:
| Endpoints | ADMIN | MEMBER | VIEWER |
|---|---|---|---|
GET accounts | yes | yes | yes |
GET posts, POST /posts/approve/{post} | yes | yes | yes |
| All other post endpoints | yes | yes | — |
GET /media, GET /media/{media} | yes | yes | yes |
| All other media endpoints | yes | yes | — |
| All tag endpoints, including reads | yes | yes | — |
Two results here are easy to trip over:
- A
VIEWERcan approve a post but cannot create one. - A
VIEWERcannot read tags. Unlike posts and media, whose read endpoints are open to viewers, every tag endpoint requiresADMINorMEMBER— soGET /tagsreturns403for a viewer.
The /panel/* endpoints are not in the table because they ignore workspace roles entirely: they
require a platform administrator account, whatever the user's role in any workspace.
Approving a post has two further conditions beyond role: the user must have approval rights in the workspace, and the workspace's plan must allow scheduling.