Errors
What the API answers when a call fails, and what to do about it.
When a call fails, SKUFlow answers with an HTTP status and a JSON body that says what went wrong in words you can show to a person:
{
"defined": false,
"code": "PLAN_UPGRADE_REQUIRED",
"status": 402,
"message": "This needs the Grow plan or higher. Upgrade in Settings → Billing.",
"data": {
"feature": "online_stores",
"requiredPlan": "grow",
"requiredAddon": null,
"currentPlan": "connect"
}
}codeis stable: branch on it, not on the message.messageis written for people. It often says what to do next.datacarries details for some codes (below). It may be missing.
Status codes
| Status | Code | What it means | What to do |
|---|---|---|---|
| 400 | BAD_REQUEST | The input is not valid: a missing field, a wrong format, a value out of range, or a rule the record breaks. | Fix the input. For validation errors, data.issues lists each field. |
| 401 | UNAUTHORIZED | No credential, or the key is wrong, revoked or expired. | Check the Authorization: Bearer skf_… header. Make a new key if this one was revoked. |
| 402 | PLAN_UPGRADE_REQUIRED | The business's plan doesn't include this (the API itself needs Pro). | Upgrade, or add the add-on named in data.requiredAddon. |
| 402 | PLAN_LIMIT_REACHED | A plan limit is used up: AI credits this month, texts or emails past the cap, or every user seat is taken. | Buy AI credits, wait for the month to reset, or change plan in Settings → Plan and billing. |
| 403 | FORBIDDEN | Your role, the key's permissions or its access level don't allow this, or a key can't do it at all. | Read the message: it names the missing permission or scope. See Authentication. |
| 404 | NOT_FOUND | No such record in this business (or one your role can't see). | Check the id and the business id in the path. |
| 409 | CONFLICT | The record's state doesn't allow it (an invoice already paid, a duplicate), or an Idempotency-Key clash. | Read the record again, then decide. |
| 409 | APPROVAL_DECLINED | You declined this call in SKUFlow. | Don't retry unless you change your mind. |
| 409 | APPROVAL_EXPIRED | The approval request expired before it was approved or used. | Call again without the approval header to ask again. |
| 409 | APPROVAL_ALREADY_RUN | That approval was already used. An approval runs once. | Read the record to see the result. |
| 409 | CONFIRMATION_INVALID | The approval header doesn't match this exact call (other inputs, endpoint, key or business). | Repeat the call exactly as it was approved, or ask again. |
| 413 | PAYLOAD_TOO_LARGE | The request body is over 40 MB. | Send less, or upload files by URL. |
| 428 | APPROVAL_REQUIRED | This action waits for a person's approval in SKUFlow. Nothing was done yet. | See Approvals. |
| 429 | TOO_MANY_REQUESTS | Too many calls in a minute. | Slow down and retry. See Rate limits. |
| 500 | INTERNAL_SERVER_ERROR | Something broke on our side. It is reported to us automatically. | Retry later. Use an Idempotency-Key on writes so a retry is safe. |
| 503 | SERVICE_UNAVAILABLE | A part of SKUFlow, or a service it relies on, is briefly unavailable. | Retry in a moment. |
Validation errors
A 400 from input validation lists every problem in message (field: what's wrong; …) and in
data.issues, with the path to each field:
{
"code": "BAD_REQUEST",
"status": 400,
"message": "dueDate: Use a date as YYYY-MM-DD",
"data": {
"issues": [{ "path": ["dueDate"], "message": "Use a date as YYYY-MM-DD" }]
}
}Plan errors in detail
402 PLAN_UPGRADE_REQUIRED names what's needed in data:
| Field | Meaning |
|---|---|
feature | The feature the call needs, such as online_stores or business_units. |
requiredPlan | The cheapest plan that has it (connect, grow, pro), or null for an add-on-only feature. |
requiredAddon | The add-on that sells it (such as phone), or null. |
currentPlan | The plan the business is on. |
402 PLAN_LIMIT_REACHED has data.feature (such as ai_credits or office_users) and, for
spending limits, data.reason. When SKUFlow can't check the plan for a moment, anything that costs
money is paused with this code too; try again in a few minutes.
Inside the app, reads are not blocked by the plan: after a downgrade you can still read and export what you made. With an API key, every call needs the Pro plan, reads included.
Approval errors in detail
428 APPROVAL_REQUIRED carries what you need to finish the call in data:
| Field | Meaning |
|---|---|
status | APPROVAL_PENDING. |
approvalId | The request's id. |
token | The value to send back in the X-SKUFlow-Approval header, sfc_…. |
summary | What the person is asked to approve, in words. |
expiresAt | When the request expires if nobody decides. |
approvalUrl | The SKUFlow page where the person approves it. |
header | X-SKUFlow-Approval. |
See Approvals for the whole flow.