MISSINdevelopersLog in

Get started

What the MISSIN API returns when a key is refused, an operation is not open to keys, a limit is reached or a mutation does not go through.

A refused key

A key that is refused before anything runs gets an HTTP error status and one GraphQL error whose message is the code, also sent as errors[0].extensions.code. The message never says more than the code.

CodeStatusMeaning
api_key_invalid401The key is malformed, unknown, revoked or expired.
api_key_creator_not_member401The member who created the key is no longer in the workspace.
api_key_conflict400The request sent two different keys, one as a bearer token and one in x-api-key.
origin_not_allowed403A publishable key was sent from an origin that is not on its list. This is checked before the key's kind.
rate_limited429The key, or the key text before it was checked, went over its limit.
api_key_required401The versioned public URL was called without an API key.
unauthenticated401A bearer token that is not a key was sent and is not a valid sign-in token.

An operation a key may not run

These are refused before anything in the operation runs, with an HTTP error status and the code as the message.

CodeStatusMeaning
operation_not_public403The operation is not open to API keys.
insufficient_access403The key's access level is below what the operation needs.
secret_key_required403A publishable key was sent to the public API. Publishable keys are refused on /graphql/v1 and /mcp for every operation, so use a secret key.
connection_key_not_supported403A key limited to one connection was sent to the API. Such a key is refused everywhere, because the API does not narrow it to its connection.

A version that does not exist

CodeStatusMeaning
unknown_api_version400The Missin-Version header names no MISSIN API version. Leave it out for the latest, or send one from the changelog. A version that has been sunset is not refused: the request is served by the oldest supported version, and Missin-Version in the response says which.

Too many requests from one address

CodeStatusMeaning
RATE_LIMITED429Over 200 requests a minute from one IP address. The code is in errors[0].extensions.code, and Retry-After says when to try again.

A mutation that did not go through

A mutation that fails for a reason you can fix returns userErrors in its payload, a list of { field, code, message } entries, with the result null. An empty list means it worked. Branch on code, not on message.

An order without a valid placed_at

Every order in MISSIN says when its buyer placed it, as placed_at. An order without one, or with one that does not name a moment in time, is refused whole: nothing is written, and MISSIN never fills the date in for you, not with the time it received the order or any other. A mutation that creates orders answers with a userErrors entry whose field names the value (placed_at, or rows.<n>.placed_at for one row of several) and one of these codes:

CodeMeaningHow to fix it
placed_at_requiredNo placed_at was given, or it is empty.Send when the order was placed.
placed_at_invalidThe value is not an ISO 8601 date and time with an explicit offset. A time with no offset (2026-01-20 13:00:05), a bare date or a date that does not exist is refused, because it would be read in a different time zone on a different server.Send 2026-01-20T13:00:05Z, or the local time with its offset: 2026-01-20T14:00:05+01:00.
placed_at_in_futureLater than now by more than five minutes.Send the moment the order was placed, not a date it is due.
placed_at_too_oldBefore 2000-01-01.Check the value. An epoch read in the wrong unit lands in 1970.

Orders from a connected store follow the same rule. A Shopify order is placed at its processedAt, the date Shopify shows on the order and uses in its own reports. A Stripe sale is placed when its invoice was finalized or, for a Checkout payment, when its PaymentIntent was created. A store order without that date is not stored, and the sync records it as failed.

An order or checkout in a currency MISSIN does not recognise

Every amount in MISSIN is in a currency it knows: one of the active ISO 4217 currencies. An order or checkout whose currency is missing, malformed or not on that list is refused whole: nothing is written, and MISSIN never stores it under another currency, not your store's, not your workspace's. The userErrors entry names the field (currency, or currency_code for a checkout) and one of these codes:

CodeMeaningHow to fix it
currency_requiredNo currency was given.Send the three-letter code of the currency the amounts are in.
currency_invalidNot a three-letter code: a symbol (£), a name (POUND) or a numeric code (826).Send the alphabetic ISO 4217 code, e.g. GBP. Case does not matter.
currency_unknownThree letters, but not an active ISO 4217 currency: a withdrawn currency (ANG, replaced by XCG), a fund or metal code (USN, XAU), or a typo (GPB).Send the currency's current ISO 4217 code.

Orders and checkouts from a connected store follow the same rule. A Shopify order is in its shop currency (shopMoney), a Stripe sale in the currency Stripe settled it in, or charged it in when there was no conversion. A store order or checkout in a currency that is not on the list is not stored, and the sync records it as failed. An imported order is in your workspace's currency, and each of its amounts carries no more decimals than that currency has (two for GBP, none for JPY, three for KWD); a row with more is refused with invalid_amount on that row's field, never rounded.

An amount too large to store

Every amount MISSIN stores holds up to fifteen digits before the decimal point, in the currency's own unit. An order, checkout or imported row with an amount past that is refused whole with amount_out_of_range, and the userErrors entry's field names the amount (rows.<n>.total_price on an import). A store order or checkout over the limit is not stored, and the sync records it as failed while the rest of the sync lands. A mutation that hits a database range limit anywhere else answers value_out_of_range.

CodeMeaningHow to fix it
amount_out_of_rangeThe amount has more than fifteen digits before the decimal point.Check the value is in the currency's major unit, not its minor unit read twice.
value_out_of_rangeA value is past a database range limit.Check the values sent; a number in the wrong unit is the usual cause.

A checkout without a start time

A checkout is stored only with the moment its basket started, as the store reports it: Shopify's created_at, or the Stripe Checkout Session's created (for a session reopened through a recovery link, the original session's). A checkout the store gives no start for is refused with checkout_started_at_required, or checkout_started_at_invalid when the start is not an ISO 8601 date and time with an offset, and the sync records it as failed. MISSIN never dates a checkout by the time it received it. The same holds for the time the store last updated it (Shopify's updated_at): a checkout without one is refused with checkout_updated_at_required, or checkout_updated_at_invalid when it is not an ISO 8601 date and time with an offset.

On the MCP server

The MCP server at https://api.missin.co.uk/mcp takes a secret key as a bearer token only, and refuses a key with the same codes: a missing key, or x-api-key on its own, gets 401, and a publishable key gets 403 with secret_key_required. It answers 403 with insufficient_scope when a tool needs a higher access level than the key has. Its status codes and limits are on the tool registry.

For AI agents: a markdown index of this site is at /llms.txt, and every page is available as markdown by adding .md to its URL.