# Recompute an enrichment

`POST /merchant/v1/enrichments/{enrichment_id}/refresh` — Merchant API · [API reference](https://developer.noryo.app/en-GB/merchant/reference)

Authentication: `bearerCredential` (http bearer).

Recomputes the merchant identity for an existing enrichment and returns a
**new** `enrichment_id`: a refresh produces a new result, so it gets a new
identity. The previous one keeps pointing at the previous snapshot.

**`Idempotency-Key` is mandatory here.** Refresh is deliberately excluded from
economic deduplication — it is the one billable path with no deduplicator, and
the key is its only protection against a network retry.

## Parameters

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `enrichment_id` | path | yes | string | `enr_` followed by a version 4 UUID, as returned by Noryo. Any other shape returns `404`. Pattern: `^enr_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`. |
| `Idempotency-Key` | header | yes | string · length 1–255 | Mandatory on refresh. See the endpoint description. Pattern: `^[\x21-\x7E]+$`. |

## Request body

`application/json` · required · Schema `RefreshRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `descriptor` | string · length ≤ 512 | yes | — |
| `amount` | number | — | — |
| `currency` | string | — | Pattern: `^[A-Z]{3}$`. |
| `occurred_at` | string · date-time | — | Pattern: `^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{1,9})?Z$`. |
| `country` | string | — | Pattern: `^[A-Z]{2}$`. |
| `mcc` | string | — | Pattern: `^[0-9]{4}$`. |

## Responses

| Status | Description |
| --- | --- |
| `200` | Recomputed and settled. |
| `400` | `invalid_request`, `invalid_json`, `identifier_required`, `invalid_idempotency_key`, `unsupported_canonicalization`. |
| `401` | `invalid_api_key`. Missing, malformed, unknown, revoked — **always the same code**. Any distinction would be an oracle. |
| `402` | `no_active_subscription`, `sandbox_quota_exhausted`. |
| `403` | `insufficient_scope`, `account_inactive`, `production_not_enabled`. |
| `404` | Unknown enrichment, or one belonging to another tenant. |
| `409` | `idempotency_key_reuse` — same key, different payload. `transaction_id_conflict` — same `external_transaction_id`, different economic input. `input_mismatch`, `refresh_not_available`. |
| `413` | `request_entity_too_large`. The body limit is 16 KiB, counted in **bytes**. |
| `415` | `unsupported_media_type`. Send `Content-Type: application/json`. |
| `429` | `rate_limited`. Nothing was computed and nothing was billed. |
| `500` | `internal_error`. The body carries no detail about the incident; quote the `request_id` to support. Retrying with the same `Idempotency-Key` is safe. |
| `503` | `engine_error`, `busy` or `pricing_not_activated`. **Nothing was billed and nothing was memorised**: retry with the same `Idempotency-Key`. |

### `200` — `Enrichment`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `enrichment_id` | string | — | Example: `"enr_7f3c1e20-…"`. |
| `merchant` | Merchant \| null | — | — |
| `merchant.name` | string | — | Example: `"McDonald's"`. |
| `merchant.category` | string | — | Example: `"alimentation.restaurant"`. |
| `merchant.logo_url` | string · uri | — | — |
| `merchant.location` | object \| null | — | **Always present**, `null` when unknown. Absent and unknown look too alike for a client to have to tell them apart. |
| `merchant.location.city` | string | — | Example: `"PARIS"`. |
| `merchant.location.postal_code` | string | — | Example: `"75018"`. |
| `merchant.confidence` | number · 0–1 | — | A **model confidence score** from 0 to 1. It should **not** be interpreted as a calibrated probability of correctness — Noryo has measured that its ordering is not monotonic above 0.95. See the guide. |
| `enrichment` | object | — | — |
| `enrichment.status` | string | — | `resolved` — identity complete and above the policy threshold. `partial` — something is missing or below threshold. `not_found` — the engine answered, and its answer is "nobody". Values: `resolved`, `partial`, `not_found`, `refresh_recalculated`. |
| `enrichment.reason` | string | — | — |
| `enrichment.environment` | string | — | Values: `sandbox`, `production`. |
| `enrichment.source` | string | — | — |
| `enrichment.customized` | boolean | — | `true` when one of **your organization's rules** (Platform → Rules) changed this response — for example a display name or a category. The Noryo result itself is stored unchanged and rules never apply outside your organization and the key's environment. `false` otherwise. A `POST` is rendered with the rules published at that moment and an idempotent replay returns that same body; a `GET` applies the rules published **now**. |
| `enrichment.rules` | array<object> | — | **Optional** — present only when `customized` is `true`: the rules that changed this response, each with the version that applied. Which field each rule changed is shown in the Platform logs. |
| `enrichment.rules[].id` | string · uuid | — | — |
| `enrichment.rules[].version` | integer ≥ 1 | — | — |
| `usage` | object | — | What **this call** cost. |
| `usage.billable` | boolean | — | — |
| `usage.units` | integer | — | — |
| `usage.deduplicated` | boolean | — | — |
| `usage.deduplicated_by` | string \| null | — | — |

## Errors named by the contract

- [`identifier_required`](https://developer.noryo.app/en-GB/errors/identifier_required)
- [`invalid_idempotency_key`](https://developer.noryo.app/en-GB/errors/invalid_idempotency_key)
- [`invalid_json`](https://developer.noryo.app/en-GB/errors/invalid_json)
- [`invalid_request`](https://developer.noryo.app/en-GB/errors/invalid_request)
- [`unsupported_canonicalization`](https://developer.noryo.app/en-GB/errors/unsupported_canonicalization)
- [`invalid_api_key`](https://developer.noryo.app/en-GB/errors/invalid_api_key)
- [`no_active_subscription`](https://developer.noryo.app/en-GB/errors/no_active_subscription)
- [`sandbox_quota_exhausted`](https://developer.noryo.app/en-GB/errors/sandbox_quota_exhausted)
- [`account_inactive`](https://developer.noryo.app/en-GB/errors/account_inactive)
- [`insufficient_scope`](https://developer.noryo.app/en-GB/errors/insufficient_scope)
- [`production_not_enabled`](https://developer.noryo.app/en-GB/errors/production_not_enabled)
- [`idempotency_key_reuse`](https://developer.noryo.app/en-GB/errors/idempotency_key_reuse)
- [`input_mismatch`](https://developer.noryo.app/en-GB/errors/input_mismatch)
- [`refresh_not_available`](https://developer.noryo.app/en-GB/errors/refresh_not_available)
- [`transaction_id_conflict`](https://developer.noryo.app/en-GB/errors/transaction_id_conflict)
- [`request_entity_too_large`](https://developer.noryo.app/en-GB/errors/request_entity_too_large)
- [`unsupported_media_type`](https://developer.noryo.app/en-GB/errors/unsupported_media_type)
- [`rate_limited`](https://developer.noryo.app/en-GB/errors/rate_limited)
- [`internal_error`](https://developer.noryo.app/en-GB/errors/internal_error)
- [`busy`](https://developer.noryo.app/en-GB/errors/busy)
- [`engine_error`](https://developer.noryo.app/en-GB/errors/engine_error)
- [`pricing_not_activated`](https://developer.noryo.app/en-GB/errors/pricing_not_activated)

## Request examples

cURL

```bash
# The contract publishes no example body for this operation: build it from the request schema.
IDEMPOTENCY_KEY=$(uuidgen)
curl -sS -g -X POST 'https://api.noryo.app/merchant/v1/enrichments/{enrichment_id}/refresh' \
  -H "Authorization: Bearer $NORYO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY"
```

JavaScript

```js
// Reuse the same key when you retry this request.
const idempotencyKey = crypto.randomUUID();

const response = await fetch("https://api.noryo.app/merchant/v1/enrichments/{enrichment_id}/refresh", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.NORYO_API_KEY}`,
    "Idempotency-Key": idempotencyKey,
  },
  // The contract publishes no example body for this operation: build it from the request schema.
});
console.log(response.status, await response.text());
```

Python

```python
import os
import uuid

import requests  # pip install requests

# Reuse the same key when you retry this request.
idempotency_key = str(uuid.uuid4())

response = requests.post(
    "https://api.noryo.app/merchant/v1/enrichments/{enrichment_id}/refresh",
    headers={
        "Authorization": "Bearer " + os.environ["NORYO_API_KEY"],
        "Idempotency-Key": idempotency_key,
    },
    # The contract publishes no example body for this operation: build it from the request schema.
)
print(response.status_code, response.text)
```

Go

```go
package main

import (
	"crypto/rand"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	// Reuse the same key when you retry this request.
	idempotencyKey := newUUID()

	// The contract publishes no example body for this operation: build it from the request schema.
	req, err := http.NewRequest("POST", "https://api.noryo.app/merchant/v1/enrichments/{enrichment_id}/refresh", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("NORYO_API_KEY"))
	req.Header.Set("Idempotency-Key", idempotencyKey)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(resp.StatusCode, string(data))
}

// newUUID returns a random (version 4) UUID: the standard library has none.
func newUUID() string {
	b := make([]byte, 16)
	if _, err := rand.Read(b); err != nil {
		panic(err)
	}
	b[6] = b[6]&0x0f | 0x40
	b[8] = b[8]&0x3f | 0x80
	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}
```

Java

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;

public class Main {
    public static void main(String[] args) throws Exception {
        // Reuse the same key when you retry this request.
        String idempotencyKey = UUID.randomUUID().toString();
        // The contract publishes no example body for this operation: build it from the request schema.
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.noryo.app/merchant/v1/enrichments/{enrichment_id}/refresh"))
            .method("POST", HttpRequest.BodyPublishers.noBody())
            .header("Authorization", "Bearer " + System.getenv("NORYO_API_KEY"))
            .header("Idempotency-Key", idempotencyKey)
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode() + " " + response.body());
    }
}
```

C#

```csharp
using System;
using System.Net.Http;

// Reuse the same key when you retry this request.
var idempotencyKey = Guid.NewGuid().ToString();

using var client = new HttpClient();
using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.noryo.app/merchant/v1/enrichments/{enrichment_id}/refresh");
request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + Environment.GetEnvironmentVariable("NORYO_API_KEY"));
request.Headers.TryAddWithoutValidation("Idempotency-Key", idempotencyKey);
// The contract publishes no example body for this operation: build it from the request schema.

using var response = await client.SendAsync(request);
Console.WriteLine((int)response.StatusCode);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

---

Canonical page: https://developer.noryo.app/en-GB/merchant/reference/refresh-enrichment
