Authentication and keys
This guide explains how API keys work: how to send one, which scopes a key can hold, and how rotation, revocation, expiry and the IP allowlist behave.
Send the key
Send the key in the Authorization header of every request, over HTTPS:
Authorization: Bearer mk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX- Only the header is accepted. A key in the query string is refused with
400 key_in_query, and the request is not logged with the key. - A key belongs to one organisation. No request names an organisation; the key decides which one you reach.
- Keys look like
mk_test_ormk_live_followed by 43 characters. The 12 characters after the prefix are the key’s prefix, which Settings → Developers and the API log show in place of the secret.
Who creates and manages keys
An administrator of the organisation creates keys in Settings → Developers → API keys. Creating, rotating and revoking a key needs the Manage settings permission. A key’s scopes cannot exceed the permissions of the person who creates it, and the check runs again on every rotation.
Each key acts as its own service user, named “API: ” followed by the key’s name. Records the key creates or changes show that name as their author in Mikono and in the audit log. The service user does not appear in the staff list and does not take a seat.
Scopes
A key holds a list of scopes. An endpoint lists the scopes it needs, and a call without them returns 403 insufficient_scope. Each scope maps to a Mikono permission, and the endpoint then applies the same permission rules as the Mikono app.
| Scope | Resource | Allows | Mikono permission |
|---|---|---|---|
customers:read | CustomersOutlets, contacts and credit fields. PII adds phones, GPS, TIN and contact names. | Read | ViewCustomers |
customers:write | Customers | Create and update | ManageCustomers |
customers:pii | Customers | Personal fields in customer responses | ViewCustomers |
products:read | ProductsCatalogue, units and empties links. | Read | ViewProducts |
products:write | Products | Create and update | ManageProducts |
prices:read | PricesPrice lists and price groups. | Read | ViewProducts |
prices:write | Prices | Create and update | ManagePricing |
routes:read | RoutesRoutes, route outlets, journey plans and salespeople. | Read | ViewOperations |
routes:write | Routes | Create and update | ManageOperations |
locations:read | LocationsWarehouses and vans. | Read | ViewInventory |
orders:read | OrdersSales orders. | Read | ViewSales |
orders:write | Orders | Create and update | ManageSales |
invoices:read | InvoicesInvoices and lines. | Read | ViewSales |
invoices:write | Invoices | Create and update | ManageSales |
returns:read | ReturnsReturns and credit notes. | Read | ViewSales |
returns:write | Returns | Create and update | ManageSales |
payments:read | PaymentsCollections and allocations. | Read | ViewFinances |
payments:write | Payments | Create and update | ManageFinances |
stock:read | StockStock levels, movements and adjustments. | Read | ViewStockLevels |
stock:write | Stock | Create and update | ManageStockAdjustments, ManageLocations |
trips:read | TripsTrips, settlements and empties. | Read | ViewOperations |
webhooks:manage | WebhooksManage webhook endpoints through the API. | Manage webhook endpoints | ManageSettings |
dms:ingest | DMSPost DMS documents, read flags and the outbound queue. | Send documents and files | ManageOperations |
dms:flags:read | DMS | Read flags | ViewOperations |
dms:outbound | DMS | Read and acknowledge the outbound queue (planned; no endpoint yet) | ManageOperations |
Without customers:pii, customer responses leave out phone numbers, GPS positions, TINs and contact names. The fields are absent, not empty.
Writes and approval tiers
Scopes never grant approval levels. A key cannot approve anything in Mikono, and no scope stands in for an approver.
API writes run through the same trusted path as van sales from Mikono Go: the same validation, stock, pricing and posting rules as the app. That path does not apply amount-tiered approval, so a document created through the API is posted, not left as a draft for an approver. Give write scopes only to systems you trust to post.
Rotation
Rotating a key issues a new secret. The old secret keeps working until the end of an overlap period, 24 hours by default and adjustable from none to 7 days, so you can deploy the new secret without downtime. The API log records which secret each call used, so you can see when your systems switched.
Revocation and expiry
- Revoking a key takes effect at once and cannot be undone. The next call returns 401.
- A key may carry an expiry date. After it, calls return 401.
IP allowlist
A key may carry a list of addresses or ranges in CIDR form, such as 203.0.113.0/24. When the list is set, calls from any other address return 403 ip_not_allowed. An empty list allows every address. The organisation can set a default list that new keys start with.
The address checked is the first hop of X-Forwarded-For as Mikono’s hosting records it. You cannot set it yourself: a forged X-Forwarded-For is replaced, and a forged CF-Connecting-IP is blocked before it reaches Mikono. If your calls leave through a proxy, NAT gateway or cloud egress, allowlist that egress address, not the address of the machine behind it. The API log shows the address each call came from, so a first test call tells you what to allow.
Keys in logs
The API log never stores the Authorization header. Anything else in a request that is shaped like a Mikono key, in a path, header or body, is masked to mk_test_[redacted] before it is stored, including keys written with Unicode look-alike characters, invisible characters or JSON escapes.
The masking has a limit: a key that is deliberately encoded, for example in base64, or split across several fields is not detected and may be stored. Send keys only in the Authorization header, never in a request body or query string.
Turning API access on
Each organisation turns API access on in Settings → Developers. Until it does, every call with its keys returns 403 api_disabled. In production, access is off until an administrator turns it on.
Authentication errors
| Status | Code | When |
|---|---|---|
| 401 | unauthorized | The key is missing, malformed, unknown, revoked or expired. |
| 401 | wrong_environment | A sandbox key was sent to production, or the reverse. |
| 403 | insufficient_scope | The key lacks a scope the endpoint needs. |
| 403 | ip_not_allowed | The call came from an address outside the key’s allowlist. |
| 403 | api_disabled | The organisation has not turned API access on. |
| 400 | key_in_query | The key was sent in the query string. |
The response says which case applies, but never whether a guessed key exists.