Authentication and conventions

This page describes rules common to every Ormuz REST API endpoint: authentication, identifier format, responses, and error handling.

Base URL

Public business REST contracts are exposed under the prefix https://api.ormuz.io/v1/. Exchanging an API key for a bearer token uses the separate endpoint POST https://api.ormuz.io/api/token.

SurfacePrefix
Token for API keyhttps://api.ormuz.io/api/token
API REST publiquehttps://api.ormuz.io/v1/

Authentification

The API uses two-step authentication. First exchange your API key for a short-lived JWT token, then send that token in the Authorization header on every request.

Step 1 — Obtain a token

HTTP
POST https://api.ormuz.io/api/token
Content-Type: application/json
{1 item
"api_key":"ormuz_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
{
"api_key": "ormuz_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

200 response

JSON
{1 item
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
}
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
}

The token carries its own JWT expiration. Standard configuration is 24 hours, but a deployment may use a shorter duration. Your client must therefore rely on token expiration and obtain a new token when needed. A revoked, suspended, or expired API key can no longer obtain a valid token.

Step 2 — Use the token

HTTP
GET https://api.ormuz.io/v1/invoices
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

The Authorization header is required on all /v1/ endpoints except the public paths listed below.

Unauthenticated paths

These endpoints do not require a token — they are accessible without an Authorization.

CheminUsage
/v1/extension-assets/*Public presentation resources declared by extensions.
/v1/extension-webhooks/*Inbound provider-webhook reception. Each extension applies its own authentication or verification contract.
/v1/journey-access/validateValidation of a temporary access capability for a User Journey.
/v1/approval-requests/assignments/*Actions performed through an approval capability intended for one specific assignment.

Authentication errors

MessageCause
Missing bearer tokenThe Authorization header is missing or malformed.
Invalid bearer tokenInvalid token, incorrect signature, or expired token.
API key is not active or unknownThe key associated with the token was revoked, suspended, or no longer exists.
API key has expiredThe API key has passed its expiration date.
API-key management: prefixes, statuses, rights, and expiration.
The Console displays key prefixes and their rights by merchant without revealing complete secrets. Enlarge

Permissions

Each API key carries one or more permission sets. Each set associates a scope — account or merchant — with a list of permissions of the form resource:action, for example invoice:read or company:write.

A permission set may be limited to a specific merchant. Account-level permissions are declared on a set without merchant_id. A key may read or modify only resources covered by its sets. When a resource belongs to an out-of-scope merchant, the API masks its existence and normally responds as if the resource were absent.

An explicit 403 response is returned when the key is valid but a specific action (for example invoice:write) is not granted.

Identifiants

Ormuz resources using a canonical identifier follow the form prefix_hex. The prefix identifies the object type and the hexadecimal part contains 32 characters representing 16 randomly generated bytes. Some resources directly backed by an external service, such as an outbound webhook endpoint, may expose the identifier supplied by that service.

cmp_0123456789abcdef0123456789abcdef   // Company
inv_0123456789abcdef0123456789abcdef   // Invoice
pci_0123456789abcdef0123456789abcdef   // Process instance
evt_0123456789abcdef0123456789abcdef   // Event occurrence

Treat all identifiers as opaque: infer neither order, creation date, nor semantics beyond the documented prefix. Canonical identifiers generated by Ormuz use prefixes and a lowercase hexadecimal part.

PrefixObjectPrefixObject
acc_Accountprd_Process definition
mer_Merchantpdr_Process revision
cmp_Companypci_Process instance
ctc_Contactpua_User action
ord_Orderpln_Launcher
inv_Invoiceapk_API key (public resource identity)
pay_Paymentevt_Event
psp_PSP paymentfrm_Formulaire

Request format

Every request with a body must send JSON with the header Content-Type: application/json. Malformed bodies return a 400.

The parameter merchant_id is required in most create requests. It must contain the merchant identifier (mer_...). The API resolves it internally and returns 400 when the merchant cannot be found.

Send only fields documented by the endpoint contract. An additional field must never be used as an implicit persistence mechanism: when it is not part of the public contract, do not assume it will be retained or returned.

Metadata

Every field named metadata follows the same Ormuz contract: a flat map whose keys are non-empty strings and whose values are only string, finite numbers, or booleans. Nested objects, arrays, and null values are forbidden.

A map contains at most 50 keys; a key is at most 64 characters; a text value at most 2,048 UTF-8 bytes; and the complete JSON representation at most 16,384 bytes. Exceeding a limit returns 400 ; the API never truncates silently.

At creation, metadata is optional and may be null. On a resource update, supplied keys are shallow-merged with the existing map; absent keys are preserved and null is rejected. To replace the map or delete a key, use respectively PUT /v1/<resource>/:id/metadata and DELETE /v1/<resource>/:id/metadata/:key.

Metadata is an unprotected surface: it carries no subtype or classification annotation. In a process, writing protected data into a metadata key is therefore an explicit declassification and requires the same consent as other reductions in protection. It never replaces secret storage.

The designer may nevertheless preserve a value's type until writing: a binding or expression to a common.amount persists its JSON integer, while a template always produces a string. The subtype is then erased. The node Get metadata value lets you reassert an expected scalar type at read time; it validates the value without converting it.

Metadata must not carry system data on which Ormuz depends for behavior. Structured provider or configuration JSON must have an explicit name, for example provider_metadata, config, or raw_response.

Response format

Single object

Every response representing a single object includes a field object identifying its type.

JSON
"invoice":{9 items
"id":"inv_0123456789abcdef0123456789abcdef"
"object":"invoice"
"merchant_id":"mer_0123456789abcdef0123456789abcdef"
"status":"issued"
"settlement_status":"unpaid"
"amount_including_tax":125000
"currency":"eur"
"created_at":"2026-06-18T10:15:30.000Z"
"updated_at":"2026-06-18T10:15:30.000Z"
}
{
"id": "inv_0123456789abcdef0123456789abcdef",
"object": "invoice",
"merchant_id": "mer_0123456789abcdef0123456789abcdef",
"status": "issued",
"settlement_status": "unpaid",
"amount_including_tax": 125000,
"currency": "eur",
"created_at": "2026-06-18T10:15:30.000Z",
"updated_at": "2026-06-18T10:15:30.000Z"
}

List

List endpoints return a stable envelope with object: "list", a data array, a has_more boolean, and a next_cursor opaque.

JSON
"list":{4 items
"object":"list"
"data":[2 items
0:{...}2 items
1:{...}2 items
]
"has_more":true
"next_cursor":"eyJ2IjoxLCJvIjoyMH0"
}
{
"object": "list",
"data": [
  { "id": "inv_0123456789abcdef0123456789abcdef", "object": "invoice" },
  { "id": "inv_fedcba9876543210fedcba9876543210", "object": "invoice" }
],
"has_more": true,
"next_cursor": "eyJ2IjoxLCJvIjoyMH0"
}

Dates

Public date/time fields are exposed in ISO 8601 UTC format. For example:

JSON
{1 item
"created_at":"2026-06-18T10:15:30.000Z"
}
{
"created_at": "2026-06-18T10:15:30.000Z"
}

Amounts

Typed amounts common.amount are integers expressed in theminor unit of the currency. For EUR, 125000 therefore represents EUR 1,250.00. Do not assume a minor unit is always one hundredth: its exponent depends on the currency.

Pagination

Potentially large lists use opaque cursor pagination. The client never calculates a position itself: it simply sends back the next_cursor received on the previous page.

ParameterDefaultMaximumDescription
limit10100Maximum number of items to return.
cursor——Opaque cursor returned by next_cursor. Do not decode or modify it.
HTTP
GET /v1/invoices?limit=20&cursor=eyJ2IjoxLCJvIjoyMH0

If has_more is true, use next_cursor unchanged for the next request. When it is false, next_cursor is null.

Write idempotency

Create operations and effectful commands that may be replayed after network uncertainty accept a header Idempotency-Key. Use one opaque value per business intent and reuse exactly the same key when you do not know whether the first request succeeded.

HTTP
POST /v1/invoices
Authorization: Bearer …
Idempotency-Key: invoice-import-2026-09-27-0042
Content-Type: application/json

Ormuz retains the first result for 24 hours. The same key with the same request replays that result; the response then contains Idempotent-Replayed: true. Reusing the same key with a different payload returns 409. Header support and whether it is mandatory or optional are declared operation by operation in OpenAPI.

Errors

Errors use a stable envelope. type describes the error family, code provides a machine identifier, and request_id lets you correlate a call with Ormuz observability. Validation errors add param and structured details.

JSON
{1 item
"error":{7 items
"type":"invalid_request"
"code":"invalid_request"
"message":"body.currency: must be an uppercase 3-letter ISO 4217 code"
"param":"body.currency"
"details":{...}1 item
"request_id":"4e36d289-9fd4-44af-86ec-a32f2a6e9350"
"correlation_id":"4e36d289-9fd4-44af-86ec-a32f2a6e9350"
}
}
{
"error": {
  "type": "invalid_request",
  "code": "invalid_request",
  "message": "body.currency: must be an uppercase 3-letter ISO 4217 code",
  "param": "body.currency",
  "details": {
    "issues": [
      {
        "code": "invalid_format",
        "path": "body.currency",
        "message": "must be an uppercase 3-letter ISO 4217 code"
      }
    ]
  },
  "request_id": "4e36d289-9fd4-44af-86ec-a32f2a6e9350",
  "correlation_id": "4e36d289-9fd4-44af-86ec-a32f2a6e9350"
}
}
Code HTTPMeaning
400Invalid request body, missing field, or incorrect value.
401Missing, invalid, or expired token, or an API key that became inactive. Renew the token when expired; a revoked, suspended, or expired key must be corrected in configuration before another attempt.
403Missing permission for this action. The message indicates which permission is required.
404Resource not found — or accessible but unauthorized for this merchant.
409State conflict: resource already in that state, duplicate on a uniqueness constraint, or ambiguous configuration requiring explicit selection.
500Internal error. Automatically replay a write only when its contract makes replay safe or idempotent; otherwise diagnose the operation state before another attempt.