Product configurations
Create a configuration
Write the terms Loans are issued under, and receive the stored configuration with the version number an issuance names.
POST
A Product configuration is the set of terms Loans are issued under: one Archetype and the values that Archetype admits. This call writes version 1 and answers
201 with the stored configuration, under the identifier the Platform composed for it.
A configuration is never edited. A later change is a new version through POST /v1/tenants/{tenant_id}/product-configurations/{id}/versions, and a Loan keeps the version it was issued under. A configuration cannot be removed either, so try the body first: the preview takes this body, runs these checks, and writes nothing. What each Archetype admits, requires and locks, with every bound, is read from the Platform rather than copied from this page.
The body is submitted whole and rejected whole. The first failure stops the walk and names its field, so a body carrying two problems reports one.
Path parameters
string
required
The Tenancy the configuration belongs to. 1–64 characters of
a–z A–Z 0–9 - _. A configuration belonging to another Tenancy answers 404, the same as one that never existed.Headers
string
Your own value, up to 255 bytes. This route carries no reference of yours — the Platform composes the identifier — so the key is what makes a retry safe: the first outcome, refusals included, is recorded and answers every identical repeat for 24 hours, marked
Idempotent-Replayed: true. The same key with a different request is 422 idempotency_mismatch.Without a key, the same body twice is two Products under two identifiers. It is the fifth line of the signed canonical string, so sign with the key you send. Retries carries the whole rule.Body
string
required
The repayment shape, fixed at creation and never changed by a later version. One of
instalment, bnpl, payday. The set is closed.object
required
The terms themselves. Every field is optional on the wire; the Archetype’s frame decides which are required, and refuses a missing one by name rather than supplying a default.
Response
string
required
The identifier the Platform composed: a four-character Archetype code, a hyphen, and a six-digit number counted within your tenancy and within that Archetype —
inst-000001, bnpl-000001, payd-000001. Every one is eleven characters. An issuance names it as configuration_id, and it never changes.string
required
The Tenancy that holds it.
string
required
The Archetype the configuration was created under. A new version carries
values alone, so this never changes.integer
required
Counts from 1 and rises by one. An issuance names it as
configuration_version; the word latest there is refused by name.string
required
RFC 3339. When the row was written, not a day a fact is about.
object
required
The stored terms, echoed back in the form they will be read in.
object
required
Every field the Archetype’s frame declares, keyed by its name, with the value a Loan issued under this version takes:
{"source": "stated", "value": …} where the version states it, {"source": "default", "value": …} where it is what the Platform reads for its absence. A default that is no value at all — no late fee, no ceiling, no guard — carries source alone. values stays exactly what was stated; effective sits beside it, never in it, and a stated field’s value is byte for byte what values answers.The defaults are read from the code issuance reads, so the effective value is what a Loan freezes.
object[]
required
What the Platform advises about the body: a value it admits and a borrower is likely to be surprised by. Each carries
code, fields it concerns and detail. An advisory refuses nothing — the version is stored as sent — and the write and its preview answer the same advisories for the same body. Empty where there is nothing.Codes are append-only, as refusal codes are: show a code you do not know rather than failing on it.
Refusals
Every refusal below is422 and carries {"error": "<sentence>", "code": "<name>"}. Branch on code; the sentence names the field and is reworded without notice.
Any query parameter on this route answers
400: the route reads none. A body stating id answers 400 too — the Platform composes it, and a field this route does not read is refused rather than ignored.
Sending it twice
This route carries no reference of yours, so anIdempotency-Key is what makes a repeat safe.
Later terms for a product you already sell are a new version, not a second create.
Why a locked field is refused rather than ignored
Why a locked field is refused rather than ignored
A value you believe is in force and is not is a dispute waiting for its Loan. A
payday body naming terms is telling the Platform the loan repays over a menu of periods; a single-period product cannot honour that, and accepting the body quietly would let the Loan be issued under terms nobody agreed to. The message names both halves — the field, and the Archetype’s own reason.