REST API reference
Every route of the hosted DSAIL service, rendered from its published OpenAPI document, so an agent can read the contract before connecting.
Base URL: https://agents.jaxon.ai. Every request and response is JSON. Every error is one envelope — {ok: false, error: {code, message, docs, ...}, versions} — and error.docs is the page on this site that resolves it (see Errors).
Authentication: the header x-jaxon-credential. Obtain an evaluation credential with no sign-up from POST /v1/credentials/evaluation; the response's credential field is the token, shown once. Evaluation credentials are scoped to compile, check and the prompt pack, and capped; a full credential is issued by Jaxon.
The document below is rendered from the published OpenAPI specification. The specification itself is GET https://agents.jaxon.ai/openapi.json, and a copy ships inside the dsail Python package as dsail.contract.openapi().
GET /health
Health
Response 200:
GET /v1/account
Entitlement and usage position (permissive stub in this release)
Response 200:
POST /v1/approvals
Save under a name and bind a human approval to an exact ruleset hash
Request body:
approver: string (required)label: any — Optional application-domain label from YOUR model (TJP-642): {domain: <a level-one id from GET /v1/vocabulary>, topic: <a short free-text level-two term>, confidence: high|medium|low, declined: bool}. Inert — it never changes a result. Stored and reported as ids only; the topic string is matched against the vocabulary and then dropped. Off-list domains are refused. Omit it, or send {declined: true}, to not label.name: any — Save the ruleset under this name as part of approving it. The binding happens BEFORE the approval is recorded, so what a person approves is findable afterwards rather than reachable only by a hash. Omit for a hash that is already saved under a name.note: anyruleset_hash: string (required)
Response 200:
approval: object (required)approved_at: string (required) — UTC, ISO 8601.approver: string (required)hash: string (required) — The exact bytes signed for. An approval follows the hash, never a name: a later revision is not covered by it.note: string | nullapprovals: array (required) — Every approval on this hash, including the new one.approved_at: string (required) — UTC, ISO 8601.approver: string (required)hash: string (required) — The exact bytes signed for. An approval follows the hash, never a name: a later revision is not covered by it.note: string | nulllabel: object | null — The ruleset's stored application-domain label (TJP-642), as ids undervocabulary_version. Null when the ruleset carries none, or when this account has labeling disabled. A label never alters a result; the level-two proposal text a caller sent is matched and dropped, never stored or returned.confidence: "high" | "medium" | "low" | null (required)declined: boolean (required)level_one: "finance" | "consumer_finance" | "capital_markets" | "insurance" | "regulatory_compliance" | "hr_workforce" | "security_access" | "security_classification" | "healthcare" | "legal_contracts" | "procurement" | "engineering_release" | "content_safety" | "other" | null (required) — Level-one domain id. Null only when declined.level_two: string | null (required) — Level-two term id, from GET /v1/vocabulary. Null when the proposal matched no published term (the proposal was counted toward promotion instead) or none was offered.updated_at: string (required) — UTC, ISO 8601.vocabulary_version: string (required)name: string | null (required) — The name these bytes are saved under after this call. Null only when none was supplied and none was already bound.namespace: string (required) — Service-internal scope identifier. For clients, not for display: never show this to a person, who identifies a ruleset by name.ok: boolean (required)ruleset_hash: string (required)saved: boolean (required) — Whether this call bound a name. The binding happens BEFORE the approval is recorded, so a refused name records no approval at all.versions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 404: the error envelope.
Response 413: the error envelope.
POST /v1/check
Validate a claim dictionary and solve it, in one call
Request body:
claims: object (required) — Claim name to value. Every declared claim must be present; a claim you could not determine is submitted as "unknown" or null.label: any — Optional application-domain label from YOUR model (TJP-642): {domain: <a level-one id from GET /v1/vocabulary>, topic: <a short free-text level-two term>, confidence: high|medium|low, declined: bool}. Inert — it never changes a result. Stored and reported as ids only; the topic string is matched against the vocabulary and then dropped. Off-list domains are refused. Omit it, or send {declined: true}, to not label.ruleset_hash: any — The hash returned by compile. Preferred after the first call.source: any — Source text, if you have not compiled it yet. Passing both is allowed and asserts they agree; a mismatch is refused.
Response 200:
Every rule in the ruleset with every assertion's own result, and nothing combined on top of them. Pure over its inputs: no timestamps, no durations, no request id, so the same ruleset and claim dictionary always produce the same bytes — through either door.
claims: object (required)bound: array (required)quantities: array — What each numeric claim was worth. Without it a check names the claims it bound and nothing about their values, so an answer of '30000 CAD' judged against a policy written in USD leaves no trace of the currency it arrived in.bound: string (required) — The DSAIL literal it became. Verbatim: the host performs no unit arithmetic.claim: string (required)conversion: object — Present only when the submitted unit differs from the declared one. 'by' is always 'engine': Z3 applies the factor as an exact rational, and the factor here is reported from the same registry for a human to check, never used to compute anything.by: string (required)factor: numberfrom: string (required)status: string (required)to: string (required)measured_in: string | null (required) — The claim's declared @unit, if any.submitted: string (required) — The value as the caller sent it.unbound: array (required) — Claims the engine had no value for — submitted as unknown, or absent. Why an assertion answered UNKNOWN is readable here.ok: boolean (required)rules: array (required)assertions: array (required)check: "TRUE" | "FALSE" | "UNKNOWN" | "AMBIGUOUS" (required) — The engine's own result, in the same four words the platform's run results use. TRUE = the assertion holds. FALSE = the assertion is violated. UNKNOWN = a claim the assertion needs was not determined. AMBIGUOUS = the assertion's evidence was contradicted — reserved: it needs an instance axis carrying several answers for one claim, and a claim dictionary holds one value per claim, so nothing produces it yet. Handle it now and a later release costs you no change.counterexample: string — The assignment that violates this assertion, from the solver. Present only on FALSE: for an UNKNOWN the solver's witness is merely a model in which the assertion could fail, and publishing it would state a determination this service did not make.name: string (required)reason_unknown: stringsource: string | nullunbridged_units: array — Unit pairs this assertion compares that no loaded converter bridges — the engine's own account of why it answered UNKNOWN.from: string (required)to: string (required)unknown_policy: stringrule: string (required)ruleset_hash: string (required)unit_library_hash: string | null (required) — The other half of a result's provenance. DSAIL numerics are dimensional, and a project may add unit converters that change what a comparison resolves to, so the ruleset hash alone no longer identifies every input. Null means no project library, which is itself reproducible: it selects the six built-in standard libraries.versions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 404: the error envelope.
Response 413: the error envelope.
Response 422: the error envelope.
Response 500: the error envelope.
POST /v1/compile
Compile a ruleset; get its hash, manifest and validation contract
Request body:
label: any — Optional application-domain label from YOUR model (TJP-642): {domain: <a level-one id from GET /v1/vocabulary>, topic: <a short free-text level-two term>, confidence: high|medium|low, declined: bool}. Inert — it never changes a result. Stored and reported as ids only; the topic string is matched against the vocabulary and then dropped. Off-list domains are refused. Omit it, or send {declined: true}, to not label.parent_hash: any — The revision this one supersedes. A revision is a new object with a parent, never an edit of the old one.source: string (required) — DSAIL ruleset source. Host annotations may appear in comments.
Response 200:
claim_schema: object (required) — JSON Schema for the claim dictionary.diagnostics: array (required)line: integer | nullmessage: string (required)severity: "error" | "warning" (required)label: object | null — The ruleset's stored application-domain label (TJP-642), as ids undervocabulary_version. Null when the ruleset carries none, or when this account has labeling disabled. A label never alters a result; the level-two proposal text a caller sent is matched and dropped, never stored or returned.confidence: "high" | "medium" | "low" | null (required)declined: boolean (required)level_one: "finance" | "consumer_finance" | "capital_markets" | "insurance" | "regulatory_compliance" | "hr_workforce" | "security_access" | "security_classification" | "healthcare" | "legal_contracts" | "procurement" | "engineering_release" | "content_safety" | "other" | null (required) — Level-one domain id. Null only when declined.level_two: string | null (required) — Level-two term id, from GET /v1/vocabulary. Null when the proposal matched no published term (the proposal was counted toward promotion instead) or none was offered.updated_at: string (required) — UTC, ISO 8601.vocabulary_version: string (required)manifest: object (required)claims: array (required)boolean_subtype: stringclaim: string (required)context: stringdata_type: "boolean" | "numeric" | "enum" (required)ordered: booleanquestion: string (required) — Shown to the extracting model.range: objectmax: numbermin: numberrequired: boolean (required)unit: string | nullunknown_allowed: boolean (required)unknown_sentinel: string — Present only when this claim's own vocabulary contains a member spelled like the sentinel. Then the string means that member and this names the value that means undetermined (null).vocabulary: arrayrules: array (required)assertions: array (required)line: integer | nullname: string (required)source: string | nullunknown_policy: "optimistic" | "pessimistic" | "neutral" (required)rule: string (required)ruleset_hash: string (required)ok: boolean (required)review: string (required) — A plain-text rendering of what this ruleset asks and decides, for a person about to approve it. Derived from the manifest on every compile, never stored, so it cannot drift from the contract a caller was handed.ruleset_hash: string (required) — sha256 of the normalised source. This is the object key.source: string (required) — The normalised DSAIL source that hashed toruleset_hash, so a caller that only ever compiles has something to show or diff without a separate load-by-name call.stored: objectparent_hash: string | nullrevision_depth: integersummary: string (required) — The same thing in one sentence, for a row in a list rather than a page a person reads.unbridged_units: array — Unit pairs this ruleset compares that no loaded converter bridges, attributed by the engine to the rule that cannot be lowered. Each one answers UNKNOWN for every claim dictionary until a converter is added.cause: "missing" | "ambiguous" (required)from: string (required)rule: string (required)to: string (required)unit_library_hash: string | null — The project unit library this compile read. Half of a result's provenance; null selects the six built-in standards.validation_contract: object (required) — Exactly what check will reject, known before submitting.versions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 413: the error envelope.
Response 422: the error envelope.
POST /v1/credentials/evaluation
Obtain an evaluation credential: no sign-up, scoped to compile and check, capped, expiring (TJP-621)
Request body:
- EvaluationCredentialRequest | null
Response 200:
An evaluation credential, minted on request with no human gate (TJP-621). The token is shown here and nowhere else — the service stores only its hash. Send it as the x-jaxon-credential header. It is scoped to compile, check and the prompt pack, capped per day and over its lifetime, and expires; every response it produces carries x-jaxon-credential-grade: evaluation.
credential: string (required) — The bearer token. Store it; it is not retrievable again.credential_id: string (required) — Names the credential without unlocking anything; safe to log.expires_at: string (required) — ISO 8601, UTC.grade: "evaluation" (required)header: string (required)limits: object (required)calls_per_day: integer (required)calls_total: integer (required)ttl_days: integer (required)ok: boolean (required)scope: arrayupgrade: stringversions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 429: the error envelope.
GET /v1/flags
This deployment's own feature flags (not the platform's)
Response 200:
POST /v1/prompt-pack
Prompt pack for source you have not compiled yet
Request body:
ruleset_hash: anysource: any
Response 200:
assembly_notes: arrayclaim_schema: object (required)integrity_rule: string (required)ok: boolean (required)prompts: array (required)answer_format: string (required)claim: string (required)context: stringdata_type: string (required)ordered_vocabulary: boolean — True when the enum was declared ordered, so its members compare with < and >.question: string (required)range: objectundetermined_value: string — The literal to send when this claim could not be determined: "unknown", or null where the vocabulary itself contains "unknown".unit: stringunknown_rule: string (required)vocabulary: arrayruleset_hash: string (required)validation_contract: objectversions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 404: the error envelope.
Response 413: the error envelope.
Response 422: the error envelope.
GET /v1/prompt-pack/{ruleset_hash}
Extraction prompts, claim schema and validation contract for a ruleset
Response 200:
assembly_notes: arrayclaim_schema: object (required)integrity_rule: string (required)ok: boolean (required)prompts: array (required)answer_format: string (required)claim: string (required)context: stringdata_type: string (required)ordered_vocabulary: boolean — True when the enum was declared ordered, so its members compare with < and >.question: string (required)range: objectundetermined_value: string — The literal to send when this claim could not be determined: "unknown", or null where the vocabulary itself contains "unknown".unit: stringunknown_rule: string (required)vocabulary: arrayruleset_hash: string (required)validation_contract: objectversions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 404: the error envelope.
Response 422: the error envelope.
GET /v1/rulesets
List named rulesets, with what each one decides
Response 200:
Every named ruleset saved for this connection, with enough per row to render a library without a second call.
namespace: string (required) — Service-internal scope identifier. For clients, not for display: never show this to a person, who identifies a ruleset by name.ok: boolean (required)rulesets: array (required)approval_count: integer (required)bound_at: string (required) — When this name last started pointing at these bytes — the ruleset's last-changed time.claim_count: integer | null (required)compiles: boolean (required) — False when the stored source no longer compiles under this engine, or its bytes are gone. The row is still returned — a listing a single unreadable entry could hide is worse than one that says so — and the counts are null.name: string (required) — The primary handle.revision_depth: integer (required)rule_count: integer | null (required)ruleset_hash: string (required)summary: string (required) — One sentence: what this ruleset asks and what it can decide. Derived per row from the manifest, never stored beside it.versions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
POST /v1/rulesets
Store a named revision of a ruleset
Request body:
label: any — Optional application-domain label from YOUR model (TJP-642): {domain: <a level-one id from GET /v1/vocabulary>, topic: <a short free-text level-two term>, confidence: high|medium|low, declined: bool}. Inert — it never changes a result. Stored and reported as ids only; the topic string is matched against the vocabulary and then dropped. Off-list domains are refused. Omit it, or send {declined: true}, to not label.name: string (required)parent_hash: anysource: string (required)
Response 200:
Response 400: the error envelope.
Response 404: the error envelope.
Response 413: the error envelope.
Response 422: the error envelope.
GET /v1/rulesets/{name}
Load a named ruleset with its full contract, revision chain and approvals
Response 200:
A stored ruleset, in the shape a compile of it would return plus what the store knows about it. This is how a saved ruleset is SHOWN — re-compiling remembered source produces a different object the moment the two disagree, and an approval follows the stored bytes.
approvals: array (required)approved_at: string (required) — UTC, ISO 8601.approver: string (required)hash: string (required) — The exact bytes signed for. An approval follows the hash, never a name: a later revision is not covered by it.note: string | nullclaim_schema: object — JSON Schema for the claim dictionary.diagnostics: arrayline: integer | nullmessage: string (required)severity: "error" | "warning" (required)label: object | null — The ruleset's stored application-domain label (TJP-642), as ids undervocabulary_version. Null when the ruleset carries none, or when this account has labeling disabled. A label never alters a result; the level-two proposal text a caller sent is matched and dropped, never stored or returned.confidence: "high" | "medium" | "low" | null (required)declined: boolean (required)level_one: "finance" | "consumer_finance" | "capital_markets" | "insurance" | "regulatory_compliance" | "hr_workforce" | "security_access" | "security_classification" | "healthcare" | "legal_contracts" | "procurement" | "engineering_release" | "content_safety" | "other" | null (required) — Level-one domain id. Null only when declined.level_two: string | null (required) — Level-two term id, from GET /v1/vocabulary. Null when the proposal matched no published term (the proposal was counted toward promotion instead) or none was offered.updated_at: string (required) — UTC, ISO 8601.vocabulary_version: string (required)manifest: object (required)claims: array (required)boolean_subtype: stringclaim: string (required)context: stringdata_type: "boolean" | "numeric" | "enum" (required)ordered: booleanquestion: string (required) — Shown to the extracting model.range: objectmax: numbermin: numberrequired: boolean (required)unit: string | nullunknown_allowed: boolean (required)unknown_sentinel: string — Present only when this claim's own vocabulary contains a member spelled like the sentinel. Then the string means that member and this names the value that means undetermined (null).vocabulary: arrayrules: array (required)assertions: array (required)line: integer | nullname: string (required)source: string | nullunknown_policy: "optimistic" | "pessimistic" | "neutral" (required)rule: string (required)ruleset_hash: string (required)name: string (required) — The name that was asked for.namespace: string (required) — Service-internal scope identifier. For clients, not for display: never show this to a person, who identifies a ruleset by name.ok: boolean (required)review: string — A plain-text rendering of what this ruleset asks and decides, for a person about to approve it. Derived from the manifest on every compile, never stored, so it cannot drift from the contract a caller was handed.revision_chain: array (required) — This hash, then its parent, back to the root.ruleset_hash: string (required) — sha256 of the normalised source. This is the object key.source: string (required) — The normalised DSAIL source that hashed toruleset_hash, so a caller that only ever compiles has something to show or diff without a separate load-by-name call.stored: objectparent_hash: string | nullrevision_depth: integersummary: string — The same thing in one sentence, for a row in a list rather than a page a person reads.unbridged_units: array — Unit pairs this ruleset compares that no loaded converter bridges, attributed by the engine to the rule that cannot be lowered. Each one answers UNKNOWN for every claim dictionary until a converter is added.cause: "missing" | "ambiguous" (required)from: string (required)rule: string (required)to: string (required)unit_library_hash: string | null — The project unit library this compile read. Half of a result's provenance; null selects the six built-in standards.validation_contract: object — Exactly what check will reject, known before submitting.versions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
Response 400: the error envelope.
Response 404: the error envelope.
Response 422: the error envelope.
GET /v1/units
Which unit standards are loaded and what this project added
Response 200:
GET /v1/units/bridge
Whether one unit converts to another, and by what factor
Response 200:
Response 400: the error envelope.
POST /v1/units/converters
Add a converter to this project's unit library
Request body:
attribution: any — Where this figure came from. Recorded alongside the edit; deliberately not part of the library hash.factor: number (required) — to = from * factor + offset. Required, and never inferred: a rate is a policy decision, so it is supplied by a person.from_unit: string (required) — The unit being converted FROM.offset: number — Affine offset; 0 for every scale but temperature.to_unit: string (required) — The unit being converted TO.
Response 200:
Response 400: the error envelope.
Response 413: the error envelope.
GET /v1/vocabulary
The application-domain vocabulary: level one, level-two terms with provenance, version history, K and the promotion rule (TJP-642)
Response 200:
The application-domain vocabulary as a machine-readable, versioned document. Level one is closed and published in full; level two lists every term that is currently in the vocabulary, with its provenance (seeded for cold start, or promoted by K distinct external accounts). Unpromoted proposals are not here — they are counts, not vocabulary.
confidence_buckets: arraycounts: objectdescription: string | nulllevel_one: array (required)description: stringid: string (required)name: string (required)level_two: array (required)aliases: arrayid: string (required)promoted_at: string | nullprovenance: "seeded" | "promoted" (required)since_version: string (required)term: string (required)ok: boolean (required)promotion: object (required)k: integer (required) — Distinct external accounts that must independently propose a term before it is published.proposal_ttl_days: integer (required)rule: string (required)published_at: string | nullversion: string (required)version_history: array (required)versions: object (required) — Which engine and which wire contract produced this response.engine: string (required)engine_version: string (required)language_version: string (required) — DSAIL language version.service_version: string (required)supported_language_versions: arraywire_version: string (required)
GET /version
Version
Response 200: