Resolve Bindings
POST /v1/binding-resolutions answers which registry fields supply your target fields, on what evidence — a cost ladder with an opt-in LLM synthesis rung.
POST /v1/binding-resolutions answers one question over the wire: "which registry fields supply these target fields, and on what evidence?" For each target field you name, the resolver returns ranked binding plans — deterministic recipes that map one or more [field-registry](registry-query) entries onto the target, each graded empirically against your corpus. It exists so an external agent (typically via MCP) can inspect a binding before anything is written with it.
Resolution climbs a cost ladder and stops at the first rung that satisfies the request: L0 returns memoized plans already stored for the target; L1 retrieves candidates by name similarity against the registry; L2 mines the corpus, testing hypothesized plans against documents where both the plan's sources and an authored label are present; L3 asks an LLM to synthesize a plan from the target's name, type, and description. L3 costs orders of magnitude more than L0–L2, so it is gated behind allow_llm and off by default; where the deployment has no LLM configured the resolver simply stops after L2, so passing the flag is always safe.
The request body carries targets[] — 1 to 100 entries of { field_key, data_type?, description? }. field_key (≤200 chars) is the schema field you want supplied; data_type (≤200 chars) and description (≤2000 chars) are the disambiguating context the L3 rung reads, and they matter: a bare name resemblance is exactly how a policy-number field once got bound to a contract id. min_trust names the empirical grade that ends the climb — inferred (default), mined, or verified — so a caller that only wants corpus-proven plans sets mined and lets the ladder keep climbing past cheap guesses.
The route takes `read` scope on a POST, deliberately — the same shape as [POST /v1/registry/query](registry-query). The handler mutates none of your data: nothing here activates, retires, or verifies a plan, no document row is read, and no document id or cell value crosses the wire. The one intended side effect is memoization: every plan the resolver proposes is written back as an inert candidate, so your workspace pays for a ladder rung at most once per target-and-plan — repeat calls answer from L0. A candidate plan does nothing until it is promoted through the platform's own verification flow.
Like other value-bearing surfaces, the endpoint requires a single-tenant credential: a key operating in the cross-tenant master view is rejected 400 ("Select one tenant for binding resolution") before the resolver runs — the memoization write-back must never land in an ambiguous tenant. The successful status is 200, not 201: you are asking a question, not creating a durable resource you manage.
/v1/binding-resolutionsBody fields
falseinferredcurl
curl -s -X POST https://api.talonic.com/v1/binding-resolutions \
-H "Authorization: Bearer tlnc_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"targets": [
{
"field_key": "invoice_number",
"data_type": "string",
"description": "The vendor invoice number as printed on the document header"
},
{ "field_key": "total_gross_amount", "data_type": "number" }
],
"min_trust": "mined"
}'Response (200)
{
"resolutions": [
{
"field_key": "invoice_number",
"bindings": [
{
"plan_id": "4a6c8e0b-2d4f-4a7c-9e1b-3f5d7a9c1e3b",
"trust": "mined",
"status": "candidate",
"ladder": "L2",
"evidence": {
"n": 184,
"agree": 179,
"agreement": 0.9728,
"ci95_low": 0.9391,
"distinct_values": 172,
"method": "mining",
"notes": null
},
"sources": [
{
"registry_id": "9b1d3f5a-7c9e-4b2d-8a4c-6e0f2b4d6a8c",
"role": "rechnungsnummer",
"canonical_name": "Rechnungsnummer"
}
],
"combine": "first_of",
"guard": {
"doc_type_id_in": null,
"doc_type_name_in": ["Rechnung", "Invoice"]
}
}
]
},
{
"field_key": "total_gross_amount",
"bindings": []
}
]
}Errors
Error responses