MeyktAPI Documentation
OpenAPI specllms-full.txtDashboard
  • Overview
  • Quickstart
  • Authentication
  • Orders
  • Files
  • Webhooks
  • Errors

Errors

Every failed request to https://api.meykt.com/v1 returns the same JSON envelope with a machine-readable code. Codes are a permanent part of the API contract: they are added over time, but never renamed or repurposed within v1. Warnings are a separate concept — a warning means the request succeeded.

#Error format

A failed request returns a single top-level error object. There is no data key on an error response.

json
{
  "error": {
    "code": "validation_failed",
    "message": "The order was rejected. No part of it was accepted — fix the listed fields and resend the complete order.",
    "doc_url": "https://www.meykt.com/en/developers/errors/validation_failed",
    "errors": [
      {
        "code": "validation_failed",
        "message": "Number must be greater than or equal to 1",
        "field": "items.0.quantity"
      },
      {
        "code": "validation_failed",
        "message": "String must contain at least 1 character(s)",
        "field": "items.1.name"
      }
    ]
  }
}
FieldAlways presentMeaning
codeyesStable machine identifier. Branch on this.
messageyesHuman-readable English text. May change at any time.
fieldnoPath to the offending field, when a single field caused the failure.
doc_urlyesLink to the reference page for this code.
errorsnoPresent on validation failures: all problems found, not just the first.

#code

code is the only value you should program against. It is stable forever — renaming a code would break existing integrations and is only possible in a new API version. Never match on message, and never parse the HTTP status alone: several distinct codes share the status 422.

New codes may be added at any time. Treat an unrecognised code as a generic failure of its HTTP status class rather than crashing.

#message

message targets a human reading a log or a terminal. The wording, punctuation and level of detail can change without notice. It often carries the specific detail that code cannot express — for example insufficient_scope names the missing scopes, and file_type_not_allowed names the file type that was actually detected. Log it; do not branch on it.

#field

field names the exact location in your request body. It is present when the failure can be attributed to one place, and it also appears on each entry inside errors[].

Two notations occur, depending on where the check happened:

  • Schema validation uses dot notation for array indexes: items.0.quantity, items.1.name, currency.
  • File reference and warning paths use bracket notation: items[0].files[0].upload_id, items[2].sku.

Do not build a parser that assumes one notation. Treat field as an opaque label for display and logging.

#doc_url

doc_url points at the reference page for that code. Every code in the table below is addressable at /developers/errors/<code>, so an automated client can fetch an explanation for a failure it has not seen before without a lookup table.

#errors

On validation_failed, the API validates the whole request and returns every problem at once (up to 50 entries), so you do not have to fix one field per round trip. Each entry has the same code / message / field shape as the outer object.

Order creation is all-or-nothing: if errors[] is present, nothing was created. Correct all listed fields and resend the complete order — not just the corrected part.

#Error codes

CodeHTTPCauseFix
invalid_api_key401Key missing, unknown, revoked or expiredCheck the Authorization: Bearer … header; verify in the dashboard that the key is still active; create a new one if needed
insufficient_scope403The key does not carry the required scopeThe message names the missing scopes; create a key with the matching scopes (there is no scope hierarchy — orders:write does not include orders:read)
invalid_json400The body is not valid JSONCheck the request body — usually a missing quote or a trailing comma
validation_failed422One or more fields invalid — nothing was createdWalk errors[]; each entry names a field and a reason; resend the corrected complete order
order_already_exists_with_different_content409The external_order_id already exists with different contentDo not invent a new number if this is meant to be the same order — align the content or resolve it in the dashboard. Use a new external_order_id only for a genuinely new order
file_not_found422upload_id unknown, never uploaded, or expiredCall POST /v1/uploads, PUT the bytes to the returned upload_url, then reference the upload_id. Unreferenced uploads expire after 14 days and must be re-uploaded
file_type_not_allowed422The file content is not an allowed type (the message names the detected type)See the file reference for allowed types. Renaming the extension does not help — the actual content is inspected
not_found404Unknown path, or an order id that is unknown or belongs to another integrationCheck the path against the reference. Order ids come from your own create and list responses
rate_limited429More than 120 requests per minute on one keyWait for Retry-After, then retry. Batch reads (GET /v1/orders?updated_since=…) instead of polling single orders
internal_error500A failure on our sideResend the identical body — duplicate protection makes this safe. Contact support if it repeats
service_unavailable503The API is temporarily unavailableWait briefly and retry

#Webhook endpoint errors

These codes only occur when managing webhook endpoints.

CodeHTTPCauseFix
webhook_url_invalid422The target URL is not a valid https URLOnly https is accepted; http:// is rejected
webhook_target_blocked422The target resolves to a private or reserved network addressUse a publicly reachable host. If you cannot expose one, poll GET /v1/orders?updated_since=… instead

#File errors are nested

file_not_found and file_type_not_allowed never appear as the top-level error.code. File problems reject the order as a validation failure, so the top-level code is validation_failed (HTTP 422) and the specific file code sits inside errors[]:

json
{
  "error": {
    "code": "validation_failed",
    "message": "The order was rejected because of file problems. Nothing was created.",
    "doc_url": "https://www.meykt.com/en/developers/errors/validation_failed",
    "errors": [
      {
        "code": "file_not_found",
        "message": "No uploaded file found for upload_id 6f1c…",
        "field": "items.0.files.0.upload_id"
      }
    ]
  }
}

Match on error.code first, then walk errors[] for the detail.

#Warnings

A warning is not an error. Warnings appear on a successful POST /v1/orders response (201), alongside the created order:

json
{
  "data": {
    "order": {
      "id": "…",
      "external_order_id": "ORDER-2026-1044",
      "is_test": true,
      "items": [{ "sku": "BECHER-GROSS", "product_linked": false }]
    },
    "warnings": [
      {
        "code": "item_product_unmatched",
        "field": "items[0].sku",
        "value": "BECHER-GROSS",
        "message": "SKU \"BECHER-GROSS\" is not linked to any product yet. The order was accepted; link it in the dashboard under Products → assignment queue."
      }
    ]
  }
}

The order was accepted and stored. Do not treat warnings as a reason to retry, to change the external_order_id, or to abort your import run.

Warning codeMeaningAction
item_product_unmatchedThe sku does not match any Meykt product yet, so product_linked is false on that itemLink it once in the dashboard under Products → assignment queue. The link applies retroactively and to all future orders with that SKU
item_missing_skuThe item was sent without a sku and therefore can never be matched automaticallySend a sku for items that should map to a Meykt product

Warnings are advisory metadata. A repeated request that hits duplicate protection returns 200 with "warnings": [] — an empty array is not a signal that a previous warning was resolved.

#Retrying safely

Retries are safe by design because POST /v1/orders is deduplicated on external_order_id: sending the identical body again returns 200 with the same order, never a duplicate. Reuse the same upload_id values in the retry — duplicate detection is computed over upload_ids, not over storage paths.

Safe to retry with the identical body:

  • 500 internal_error — a failure on our side; the order may or may not have been stored, and the retry resolves that either way.
  • 503 service_unavailable — the API is temporarily out of service.
  • 429 rate_limited — wait for the seconds given in the Retry-After header first. The limit is 120 requests per minute per key; X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset are returned on every response.
  • Network timeouts and dropped connections where you never saw a response — this is the case duplicate protection exists for.

Do not retry unchanged (fix first):

  • 400 invalid_json, 422 validation_failed, 422 file_not_found, 422 file_type_not_allowed — the same body will fail identically. Correct it, then resend the complete order.
  • 401 invalid_api_key, 403 insufficient_scope — a key or scope problem; retrying burns rate limit without changing anything.
  • 404 not_found — the path or id is wrong.
  • 409 order_already_exists_with_different_content — the number is taken by an order with different content. Meykt never overwrites an order through the API, and there is no endpoint to change an already-sent order; resolve it in the dashboard, or use a new external_order_id only if this really is a different order.

A workable client policy: retry 5xx and 429 with exponential backoff (for example 1 s, 5 s, 30 s, 2 min) and a bounded number of attempts, honouring Retry-After when present; route everything else to a dead-letter queue for a human to inspect.

Treat 200 and 201 identically when creating an order. 201 means the order was newly created, 200 means an identical order already existed. Both return the same order object under data.order.

Machine-readable version of this page: https://www.meykt.com/developers/errors.md

On this page

  • Error format
  • code
  • message
  • field
  • doc_url
  • errors
  • Error codes
  • Webhook endpoint errors
  • File errors are nested
  • Warnings
  • Retrying safely

Base URL https://api.meykt.com/v1 · Machine-readable: openapi.json · llms-full.txt

Imprint · Privacy · Terms