Errors
When something goes wrong, MarginFront returns an HTTP status code and a JSON body describing what happened. This doc translates the most common ones from developer-speak into plain English, plus how to fix each one.The shape of an error response
Every error looks roughly like this:message is usually the most helpful — it tells you exactly which field is wrong and why.
For server errors (500s), message is often a generic string; the actual problem is on MarginFront’s side and the response won’t tell you how to fix it (because it’s not your fault).
400 Bad Request
What happened: Something in your request is malformed. Usually a missing required field or a field with the wrong type.
Most common causes:
- You forgot a required field (check the resource’s doc for which fields are required)
- A UUID field isn’t a valid UUID format
- A date field isn’t valid ISO 8601
- An enum field has a value that isn’t in the allowed list
- An email field isn’t a valid email
message field — it usually names the specific field that’s wrong. Fix it and retry.
Example:
name, fix the agentId to be a valid UUID.
401 Unauthorized
What happened: Your API key is missing, malformed, or wrong.
Most common causes:
- You forgot the
x-api-keyheader entirely - The header name is wrong (e.g., using
Authorization: Bearer— that’s for JWT tokens, not API keys) - The API key is from a different environment (test vs live)
- The API key was revoked in the dashboard
- A typo when copy-pasting the key
- Double-check the header is exactly
x-api-key: mf_sk_... - Copy a fresh key from the dashboard
- Re-export it:
export MF_API_SECRET_KEY="..." - Try again
403 section below.
403 Forbidden
What happened: Your API key is valid, but you’re trying to do something it’s not allowed to do.
Most common causes:
- You used a publishable key (
mf_pk_*) on a write operation. Publishable keys are read-only by design — POST/PUT/PATCH/DELETE are rejected. Use a secret key (mf_sk_*) for writes. - You hit an endpoint that requires a human user session (not an API key). These include:
GET /v1/users/mePOST /v1/invitations/accept/:token- Team invitation endpoints
- A few org management actions
- If the response message mentions “publishable keys cannot perform write operations”, switch to a secret key. See authentication.md for the key type reference.
- If the endpoint is a “user-scoped” endpoint, you can’t use an API key — you need to be logged in as a human via the dashboard instead.
404 Not Found
What happened: The thing you’re trying to read/update/delete doesn’t exist.
Most common causes:
- Wrong UUID in the URL (typo, or using an old deleted record’s ID)
- The record exists but in a DIFFERENT org than yours
- You’re creating a subscription but the
customerId/agentId/planIdyou reference doesn’t exist - The URL itself is wrong (e.g., typo in the resource name)
- Double-check the ID by listing the resource first and finding the correct ID
- Verify the ID belongs to your org (if you’re using a different API key than usual, make sure it’s pointing at the same org)
- Check the URL for typos
409 Conflict
What happened: The thing you’re trying to create already exists, or your update would violate a uniqueness constraint.
Most common causes:
- Creating a customer with an
externalIdthat already exists in this org - Creating an agent with an
agentCodethat already exists in this org - Creating a signal with a name that already exists for that agent
- Deleting an agent/customer/plan that still has dependent records (e.g., deleting a customer that has an active subscription)
- For duplicate
externalId/agentCode/ name: either pick a different one, or update the existing record instead of creating a new one - For delete-with-dependents: delete or reassign the dependent records first, then retry the delete
422 Unprocessable Entity
What happened: Your request was structurally valid (valid JSON, required fields present), but the combination of values doesn’t make sense.
Most common causes:
- Creating a subscription with an
endDateearlier than thestartDate - Billing cycle math that doesn’t work (e.g.,
billingCycle: "custom"withoutcustomCycleDays) - An
agentIdthat belongs to a different org than the customer
message field carefully — it’ll describe the specific inconsistency.
429 Too Many Requests
What happened: You’re hitting the API faster than the rate limit allows.
How to fix:
- Slow down your request rate
- If logging usage events, batch them (up to 100 per call) instead of one per request
- Check response headers for
Retry-Afterto see how long to wait
500 Internal Server Error
What happened: Something broke on MarginFront’s side. This is NOT your fault.
Most common causes:
- A bug in MarginFront’s code
- A database connection issue
- An upstream service (Stripe, Resend, etc.) being unavailable
- Retry once after a few seconds — transient errors are common
- If it persists, email
[email protected]with:- The exact URL and method you called
- The request body (with any API keys redacted)
- The full error response body
- A timestamp (roughly when you saw the error)
502 / 503 / 504 — Gateway errors
What happened: MarginFront’s API is temporarily unreachable or down.
How to fix:
- Wait a minute and retry
- Check MarginFront’s status page if one exists
- If it’s sustained, email
[email protected]
”I get a response but no body”
A few endpoints return an empty body on success (typicallyDELETE returning 204 No Content). That’s expected — the status code is the real signal, not the body.
If you expected a body and got nothing on a different status code, treat it as a bug and report it.
”The error message mentions a field I didn’t send”
This usually means a required field is missing, or a field you sent has the wrong type. The error’smessage array tells you exactly which field — read it carefully and cross-reference with the resource’s doc file (e.g., customers.md) for the required and optional fields.
Response-level error codes (inside a 200 OK)
Some endpoints — particularly POST /v1/usage/record — return 200 OK even when individual records in a batch fail. The failures appear in the results.failed[] array in the response body, each with a code and a stored flag.
The stored flag
Every failed record tells you whether the event was saved to the database:
stored: true— The event IS in the system (withcost: null). Do NOT retry — retrying will create a duplicate. Instead, fix the root cause (map the model in the dashboard) and the event will be backfilled automatically.stored: false— The event was NOT saved. Safe to retry after fixing the issue.
Error codes
| Code | Stored? | What happened | What to do |
|---|---|---|---|
NEEDS_COST_BACKFILL | Yes | The event is saved with usageCost: null for one of two reasons: the model + modelProvider combination isn’t in the pricing table, OR it is in the table but has no rate for the cache tokens your event reported (MarginFront flags it rather than pricing that cache at $0). The error message says which. | Go to the dashboard → Usage Events → “Needs attention.” If the model is unknown, map it to a known one. If the model is known but missing cache-token pricing, email [email protected] to have cache pricing added. Once resolved, cost is calculated retroactively and future events auto-resolve. |
INTERNAL_ERROR | No | Something unexpected broke on our side during event processing. | Safe to retry. If it keeps happening, contact support with the rawEventId from the response. |
VALIDATION_ERROR | No | A required field is missing or has the wrong type (e.g., modelProvider not provided, inputTokens is negative). | Read the error message to see which field failed. Fix the request and resend. |
Example: a batch with one success and one backfill
200 for both.
See usage-events.md for the full endpoint documentation and mapping workflow.
Still stuck?
If none of the above match what you’re seeing, email[email protected] with:
- The exact curl command you ran (API key REDACTED)
- The full response status and body
- What you expected to happen

