# Declare what was supplied for an account, over a period

`POST /transactions/v1/coverage-windows` — Transaction Intelligence · [API reference](https://developer.noryo.app/en-GB/transaction-intelligence/reference)

Authentication: `txnApiKey` (http bearer).

Coverage is a fact about an account and a period, not about a transaction. It answers "have all the operations on this account between these two dates been supplied to you?", and it exists precisely when there is NO transaction to send: a month with no direct debit is the case where the declaration matters most. That is why it has its own resource rather than a field on the enrichment. Without it, we will never say that a series is late: a missing due date proves nothing as long as we do not know whether the account was being observed, and `lifecycle.state` stays `unknown`. And we verify nothing: what you declare is recorded as a caller assertion (`caller_asserted`). Provenance is not a field you choose. The call is idempotent by construction: intervals that touch are merged, so an hourly synchronisation does not manufacture intervals.

## Request body

`application/json` · required · Schema `CoverageWindow`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `account_hint` | object | yes | The account concerned. `iban` when it has one, otherwise `external_account_id`, your own identifier, for cards, wallets and non-SEPA rails. At least one of the two. Neither is stored: we keep only an opaque fingerprint, scoped to your workspace, the same one as on the enrichment, without which the coverage would never meet the series it qualifies. |
| `account_hint.iban` | string | — | Pattern: `^[A-Z]{2}[0-9]{2}[A-Z0-9]{10,30}$`. |
| `account_hint.external_account_id` | string · length 1–128 | — | — |
| `covered_from` | string · date | yes | — |
| `covered_to` | string · date | yes | We do not certify what has not happened yet: a future date is rejected. |
| `completeness` | string | — | `complete` means something precise: you assert that all the operations on this account over this interval have been supplied to us. It is the only value that allows us to conclude from an absence. `partial` and `unknown` do not: ten calls in October may be ten operations out of a hundred. Values: `complete`, `partial`, `unknown`. |

## Responses

| Status | Description |
| --- | --- |
| `200` | Coverage recorded, or merged with a neighbour. |
| `400` | Unreadable body, or undeclared host. |
| `401` | Key missing, unknown or revoked. |
| `403` | Organisation or workspace inactive. |
| `413` | Body too large. |
| `415` | The body must be application/json. |
| `422` | Closed schema: unknown field, account missing or malformed, non-existent day, interval reversed or in the future, unknown completeness. `errors[].code` names the rule, and the list is the runtime's own, by construction: `must_be_object`, `unknown_field`, `required`, `malformed_iban`, `must_be_non_empty_string`, `too_long`, `contains_control_character`, `account_identity_required`, `must_be_iso_date`, `after_covered_to`, `unknown_completeness`, `interval_in_future`. `must_be_iso_date` covers form and calendar (`2026-02-30` is rejected). `interval_in_future`: `covered_to` beyond tomorrow, by the server's date in UTC. `provenance` is not an input field: the closed schema rejects it as `unknown_field`, and the store never sees it. |
| `429` | `rate_limited`: the operational rate limit has been reached, for this key or for the workspace (the `detail` says which). Nothing was computed, nothing was stored, no event was emitted. Replay after `Retry-After`. See `x-noryo-rate-limit`. |
| `500` | Internal error. |

### `200` — `CoverageWindowResult`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `covered_from` | string · date | yes | — |
| `covered_to` | string · date | yes | — |
| `completeness` | string | yes | Values: `complete`, `partial`, `unknown`. |
| `provenance` | string | yes | Always `caller_asserted`: we record what you assert, we do not verify it, and you cannot declare anything else. Values: `caller_asserted`. |
| `merged_intervals` | integer ≥ 0 | yes | — |
| `policy_version` | string | yes | — |
| `note` | string | — | — |
| `request_id` | string | yes | — |

Example — enregistree

```json
{
  "covered_from": "2026-07-01",
  "covered_to": "2026-07-31",
  "completeness": "complete",
  "provenance": "caller_asserted",
  "merged_intervals": 0,
  "policy_version": "cov_v1",
  "note": "",
  "request_id": "req_01J9…"
}
```

Example — Two adjoining declarations become one.

```json
{
  "covered_from": "2026-07-01",
  "covered_to": "2026-08-15",
  "completeness": "complete",
  "provenance": "caller_asserted",
  "merged_intervals": 1,
  "policy_version": "cov_v1",
  "note": "",
  "request_id": "req_01J9…"
}
```

## Errors named by the contract

- [`invalid_api_key`](https://developer.noryo.app/en-GB/transaction-intelligence/errors/invalid_api_key)
- [`account_inactive`](https://developer.noryo.app/en-GB/transaction-intelligence/errors/account_inactive)
- [`request_entity_too_large`](https://developer.noryo.app/en-GB/transaction-intelligence/errors/request_entity_too_large)
- [`unsupported_media_type`](https://developer.noryo.app/en-GB/transaction-intelligence/errors/unsupported_media_type)
- [`rate_limited`](https://developer.noryo.app/en-GB/transaction-intelligence/errors/rate_limited)
- [`internal_error`](https://developer.noryo.app/en-GB/transaction-intelligence/errors/internal_error)

## Rate limits

This operation consumes the rate limit `debit_ti_v1`.

`debit_ti_v1` — operational_burst_protection · token_bucket

- per key: 120 requests / minute (capacity 120, refill 2/s)
- per workspace: 600 requests / minute (capacity 600, refill 10/s)

« 120 requetes / minute » est traduit en seau a jetons : capacite 120 (la rafale toleree) rechargee a 2 jetons / seconde (le regime durable). Une clef au repos peut envoyer 120 requetes d'un coup, puis 2 par seconde ; sur la premiere minute apres un repos, jusqu'a 240 passent. Le workspace, lui, borne la somme de toutes ses clefs a 600 / minute (capacite 600, 10 / s) : cent clefs ne font pas cent fois la limite.

It is not: `sandbox_lifetime_quota`, `production_usage_quota`, `billing_entitlement`, `commercial_promise`.

## Request examples

cURL

```bash
# The contract publishes no example body for this operation: build it from the request schema.
curl -sS -X POST 'https://api.noryo.app/transactions/v1/coverage-windows' \
  -H "Authorization: Bearer $NORYO_API_KEY"
```

JavaScript

```js
const response = await fetch("https://api.noryo.app/transactions/v1/coverage-windows", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.NORYO_API_KEY}`,
  },
  // 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 requests  # pip install requests

response = requests.post(
    "https://api.noryo.app/transactions/v1/coverage-windows",
    headers={
        "Authorization": "Bearer " + os.environ["NORYO_API_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 (
	"fmt"
	"io"
	"net/http"
	"os"
)

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

	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))
}
```

Java

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

public class Main {
    public static void main(String[] args) throws Exception {
        // 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/transactions/v1/coverage-windows"))
            .method("POST", HttpRequest.BodyPublishers.noBody())
            .header("Authorization", "Bearer " + System.getenv("NORYO_API_KEY"))
            .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;

using var client = new HttpClient();
using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.noryo.app/transactions/v1/coverage-windows");
request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + Environment.GetEnvironmentVariable("NORYO_API_KEY"));
// 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/transaction-intelligence/reference/declare-coverage-window
