The format catalog
The catalog gives a read-only inventory of the formats the ingestion engine can parse. It is global-first and static: built-in parsers carry no tenant, so every authenticated caller sees the same response. The catalog uses a
region → family → variant tree that matches the canonical format descriptor axes.
XX for region-neutral formats. Even a single-canonical-layout family (for example camt) names its layout as the variant (camt053 above).
The built-in catalog holds these format keys:
The catalog takes no path, query, or body parameters. The tenant has no effect on the built-in catalog.
Layout templates
When a file uses an operator- or brand-specific fixed-width layout that no built-in parser covers, register a layout template. A template namespaces a positional layout under the
{region, family, variant} axes. The parse path resolves it as an additive layout source for your tenant.
Every submission and edit runs through a well-formedness gate before storage. Overrun, overlap, missing-required fields, a mis-marked money column, or an unknown kind reject with 422. A zero-field record rejects with 400. Matcher never stores that template. Matcher does not use a template whose key matches a built-in format.
Money third rail: the field named
amount is the money column, and it must declare kind: "decimal". The submission gate rejects an amount field that omits or mis-marks its kind. Matcher reads amount as a number with an explicit decimal point and applies no implied decimal places: 000000010050 reads as 10050.Create a template
region: ISO alpha-2 region (uppercased) orXX.family: closed-enum format family the template namespaces under.variant: open operator/brand axis (must be non-blank).discriminatorStart/discriminatorLength: the byte range the parser reads to select a record type.records[]: each record type with its fixedwidth(bytes) and ordered positionalfields. Offsets are zero-based.fields[].name:external_id,amount,currency,date, anddescriptionmap to the transaction. Every other name goes into metadata. Without acurrencyfield, the currency isBRL.fields[].kind:string,decimal(money/numeric verbatim token, parsed downstream), ordate.requiredFields(optional): field names the variant must declare across its record types.
201 with the stored template, including its formatKey (for example br/cnab400/acme-cobranca), the discriminator, the full positional layout, and recordWidths.
List and get templates
Update and delete a template
PUT is a full replace, not a sparse patch. The byte-range invariants are whole-layout properties. The replacement runs through the same well-formedness gate the create path enforces. A failing layout rejects with 422, and the stored template stays unchanged.
204. A missing template returns 404.

