Authentication
How API keys are issued, what they look like, how to send them, and why a request is rejected with 401 or 403.
Getting a key
API keys are issued by the shop operator, not by you. In the shop’s admin area, under Settings > System > API access, the operator creates an access for your app and sets:
- Scopes: what the key may do, for example create orders or read customers. See the scope reference.
- Environment: live or test. See Live and test environments.
- Shop: the shop under which all orders of this key are created. Required for the scope
orders.write; withorders.readthe key reads the orders of this shop. - Referrer: the default referrer for orders that do not send their own
referrer_id. - Match existing customers by email: off by default. See How customers are matched.
- Requests per minute: 120 by default. See Rate limits.
- Expiry date (optional): the key stays valid until the end of that day.
Ask the operator for the scopes your integration needs. A key can hold several scopes.
Key format
A key consists of four parts separated by underscores:
omn_live_AbCd1234_0123456789abcdefghijABCDEFGHIJ12
│ │ │ └─ secret, 32 letters and digits
│ │ └─ prefix, 8 letters and digits
│ └─ environment: live or test
└─ fixed marker
Keys of a test access start with omn_test_. Keys are case-sensitive.
The operator sees the full key exactly once, right after creating or renewing it. After that only the prefix is visible in the admin area. Store the key like a password: in a secret store or an environment variable, never in source code, logs or request bodies.
If a key is lost or compromised, ask the operator to renew it. The old key stops working immediately. The operator can also pause or revoke an access at any time.
Sending the key
Send the key in the Authorization header of every request:
GET /api/v1/ping HTTP/1.1
Host: shop.example.com
Authorization: Bearer omn_live_AbCd1234_0123456789abcdefghijABCDEFGHIJ12
Accept: application/json
For requests with a body, also send Content-Type: application/json.
curl -s https://shop.example.com/api/v1/ping \
-H "Authorization: Bearer $OMNEYA_API_KEY" \
-H "Accept: application/json"
Replace shop.example.com with the shop’s own address.
Scopes
Each endpoint requires one scope, except GET /ping, which works with any valid key. GET /ping returns the scopes of your key, so you can check them before you call anything else.
If the key lacks the required scope, the API answers 403 with the code insufficient_scope. error.details.required lists the scopes the endpoint needs, error.details.missing the ones your key does not have:
{
"error": {
"code": "insufficient_scope",
"message": "The API key is missing a required scope.",
"details": {
"required": ["customers.write"],
"missing": ["customers.write"]
}
}
}
A 403 does not go away on retry. Ask the operator to add the scope.
Why a request is rejected with 401
The API answers 401 with the code unauthorized when the key:
- is missing, or the header is not
Authorization: Bearer <key> - does not match the key format
- is unknown or has a wrong secret
- belongs to an access that is paused, expired or revoked
- was renewed, and you still send the old one
The response is always the same, whatever the reason:
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key.",
"details": []
}
}
The API does not tell you which of the reasons applies. This is deliberate: different answers would reveal which keys exist. Check the key you send, then ask the operator whether the access is active.
Repeated failed attempts with the same key prefix from the same IP address lead to 429 rate_limited. See Rate limits.
Next step
Your first request shows the full round trip with GET /ping.