# Formats

> JSON, encoding, maximum size, the exact format of each request field, the canonical form used to compare two transactions, and the format of returned identifiers.

## Transport

| Item | Rule |
|---|---|
| Protocol | HTTPS, to the configured base URL |
| Body of `POST` routes | A JSON object, UTF-8 encoded, sent with `Content-Type: application/json` |
| Body size | 16 KiB at most (16,384 bytes), counted in **bytes**, not characters. Beyond: `413 request_entity_too_large` |
| Response bodies | JSON. Errors are `application/problem+json` |
| `GET` route | No body |

The 16 KiB limit comfortably covers one transaction; it exists because the API processes one transaction per request, not a file.

## Request fields

| Field | Type | Exact format | Example |
|---|---|---|---|
| `descriptor` | string | Required, not empty (not whitespace only), 512 characters at most | `"CB MCDONALDS PARIS 4519"` |
| `amount` | number | A finite JSON number; a string is refused | `12.40` |
| `currency` | string | ISO 4217, three **upper-case** letters | `"EUR"` |
| `occurred_at` | string | ISO 8601 date and time **in UTC with the `Z` suffix**, optional fraction of a second (1 to 9 digits) | `"2026-09-06T11:42:00Z"` |
| `country` | string | ISO 3166-1 alpha-2, two **upper-case** letters | `"FR"` |
| `mcc` | string | Four digits, as a string | `"5814"` |
| `external_transaction_id` | string | 1 to 255 characters; create only | `"tx_8f21c0"` |

Only `descriptor` is required. An optional field you do not have must be **omitted**: the value `null` is refused for each of them. See [Validation](https://developer.noryo.app/en-GB/merchant/requests/validation).

## Why upper case

`eur` is rejected with `400`, and so is `fr`. This is deliberate: the canonical form compares `currency`, `country` and `mcc` **verbatim**, so `EUR` and `eur` would be two distinct economic identities and two invoices for what you meant as one call. The validator refuses the ambiguity rather than normalising behind your back.

## The canonical form

To decide whether two requests carry the same transaction (idempotency and deduplication), Noryo compares a canonical form of the six economic fields:

| Field | Processing before comparison |
|---|---|
| `descriptor` | Unicode NFC normalisation, lower case, runs of whitespace collapsed to one space, leading and trailing whitespace removed |
| `amount` | Decimal representation to 15 significant digits |
| `occurred_at` | Converted to UTC and truncated to the second |
| `currency`, `country`, `mcc` | None: compared verbatim |
| Absent field | Stays absent: an omitted field and a present field make two different inputs |

As a result, `"CB  McDonalds Paris"` and `"cb mcdonalds paris"` are the same input; so are `2026-09-06T11:42:00.250Z` and `2026-09-06T11:42:00Z`; so are `12.4` and `12.40`. On the other hand, a request carrying `amount` and a request without it are two transactions.

This form is only used for comparison. The raw descriptor itself is not retained.

## Identifiers returned by the API

| Identifier | Shape | Notes |
|---|---|---|
| `enrichment_id` | `enr_` followed by a version 4 UUID, lower case | Random: it reveals neither an order nor a volume. A malformed identifier returns `404`. |
| `request_id` / `Noryo-Request-Id` | `req_` followed by a version 7 UUID | Time-ordered, useful for sorting your logs. |
| API key | `nry_mer_sbx_<key_id>.<secret>` or `nry_mer_live_<key_id>.<secret>` | See [API keys](https://developer.noryo.app/en-GB/merchant/authentication/api-keys). |

Treat these identifiers as opaque: store and compare them as they are, without extracting meaning from them.

## Returned values

| Field | Shape |
|---|---|
| `merchant.confidence` | A number between 0 and 1 |
| `merchant.category` | A text code, for example `alimentation.restaurant` |
| `merchant.logo_url` | A URI |
| `merchant.location` | An object `{ "city", "postal_code" }` or `null`. See [Location](https://developer.noryo.app/en-GB/merchant/models/location). |
| `Retry-After` | A whole number of seconds |

---

Canonical page: https://developer.noryo.app/en-GB/merchant/requests/formats
