Answer one interview card
POST/api/public/v1/aip/drafts/{public_id}/intent-policies/{intent_policy_id}/answers beta
accept the recommended answer, or change it with values (a dictionary card), question (an agent question card) or fallback Ask or Block (the fallback card). An answer that changes nothing the rules read (an accept, or the value already in force) is only recorded: no job, the revision and confirmed stay. Otherwise the draft's revision moves and the stored cases re-run at once, code-only; cases for added values are then written in the background (busy: topping_up, blocking nothing), or every case again when more than half went stale. 422 UNKNOWN_CARD, 422 INVALID_PATTERN, 503 ENGINE_UNAVAILABLE.
curl --fail-with-body -X POST 'https://app.openlatch.ai/api/public/v1/aip/drafts/<draft_public_id>/intent-policies/<intent_policy_id>/answers' \ -H "Authorization: Bearer $OPENLATCH_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"card_key":"<card_key>","choice":"accept"}'import jsonimport osimport urllib.request
body = '{"card_key":"<card_key>","choice":"accept"}'request = urllib.request.Request( 'https://app.openlatch.ai/api/public/v1/aip/drafts/<draft_public_id>/intent-policies/<intent_policy_id>/answers', method='POST', data=body.encode(), headers={ 'Authorization': 'Bearer ' + os.environ['OPENLATCH_API_KEY'], 'Content-Type': 'application/json', },)with urllib.request.urlopen(request) as response: text = response.read().decode() print(json.dumps(json.loads(text), indent=2) if text else response.status)#!/usr/bin/env bashset -euo pipefail
curl -sS --fail-with-body -X POST 'https://app.openlatch.ai/api/public/v1/aip/drafts/<draft_public_id>/intent-policies/<intent_policy_id>/answers' \ -H "Authorization: Bearer $OPENLATCH_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"card_key":"<card_key>","choice":"accept"}' | jq .$headers = @{ Authorization = "Bearer $env:OPENLATCH_API_KEY"}$body = '{"card_key":"<card_key>","choice":"accept"}'Invoke-RestMethod -Method POST -Uri 'https://app.openlatch.ai/api/public/v1/aip/drafts/<draft_public_id>/intent-policies/<intent_policy_id>/answers' -Headers $headers -ContentType 'application/json; charset=utf-8' -Body $body | ConvertTo-Json -Depth 20Authorization
Section titled “Authorization”| Role in the organization | This endpoint |
|---|---|
owner | Allowed |
admin | Allowed |
editor | Allowed |
viewer | Not allowed |
A key carries the role its owner holds in the organization. See Authentication.
API key scope: aip:write
Path parameters
Section titled “Path parameters”| Parameter | Type | Description |
|---|---|---|
public_id | string | Required. |
intent_policy_id | string (uuid) | Required. |
Header parameters
Section titled “Header parameters”| Parameter | Type | Description |
|---|---|---|
Idempotency-Key | string or null | Optional. Makes the request safe to retry: the same key and the same request, within 24 hours, returns the stored response with Idempotent-Replayed: true and runs once. |
Request body
Section titled “Request body”| Field | Type | Description |
|---|---|---|
card_key | string | Required. |
choice | string — one of accept, change | Required. |
fallback | string — one of Ask, Block or null | |
question | string or null | |
values | array of string or null |
Response
Section titled “Response”- 200 OK — the call succeeded.
- 400 Bad Request —
BAD_REQUEST - 401 Unauthorized —
UNAUTHORIZED - 402 Payment Required —
license_expired - 403 Forbidden —
FEATURE_DISABLED,FORBIDDEN,INSUFFICIENT_SCOPE - 404 Not Found —
NOT_FOUND - 409 Conflict —
GROUNDING_IN_FLIGHT,IDEMPOTENCY_IN_PROGRESS - 422 Unprocessable Content —
IDEMPOTENCY_KEY_REUSED,INVALID_ID,INVALID_PATTERN,UNKNOWN_CARD,VALIDATION_ERROR - 429 Too Many Requests —
TOO_MANY_REQUESTS - 500 Internal Server Error —
INTERNAL_SERVER_ERROR,tenant_isolation_violation - 503 Service Unavailable —
ENGINE_UNAVAILABLE,FEATURE_STATE_UNAVAILABLE,SERVICE_UNAVAILABLE
Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
data | object | Required. One intent policy of a draft. |
data.busy | string or null | What runs on the intent policy: grounding, cases (its stored cases checked again), fix, or topping_up (cases written for the values an answer added, appended when ready; it blocks nothing). |
data.capability | string or null | |
data.cards | array of object | Required. |
data.cards[].answer | object or null | |
data.cards[].key | string | Required. |
data.cards[].kind | string — one of dictionary_values, agent_question, fallback | Required. |
data.cards[].question | string | Required. |
data.cards[].recommended | object | Required. |
data.cases | array of object | Required. |
data.citation | object or null | Required. The framework preset rule this intent policy came from, edited when its sentence differs; null for anything not drawn from a framework preset. |
data.citation.edited | boolean | Required. |
data.citation.entries | array of object | Required. |
data.citation.items | array of object | Required. |
data.citation.license_url | string | Required. |
data.citation.preset_key | string | Required. |
data.citation.preset_title | string | Required. |
data.citation.rule_id | string | Required. |
data.citation.source_commit | string | Required. |
data.citation.source_date | string | Required. |
data.citation.source_sentence | string | Required. |
data.citation.version | integer — 1 | Required. |
data.confirmed | boolean or null | |
data.deferred | object or null | The deferred part's gap class and fallback; null when it has none. |
data.deferred.class | object or null | |
data.deferred.fallback | string — one of Ask, Block | Required. |
data.dimension | string — one of quality, economics, security, safety, compliance | Required. |
data.fallback | string — one of Ask, Block or null | |
data.fix | object or null | |
data.fix.attempts_left | integer | Required. How many more fixes may be asked for (aip_draft_fix); the check loop never spends one. |
data.fix.available | boolean | Required. |
data.fix.diff | object | Required. |
data.fix.fix_id | string | Required. |
data.fix.reason | object or null | Why the proposal is not simply the fix: breaks_passing_case (a passing case fails under it), not_enforceable (it grounds to a refusal), unchanged (the same sentence), still_failing (a case still fails with it, or the attempts ran out), refused_rewrite (an enforceable rewrite of a refused sentence); null for a proposal with none of these. |
data.fix.requested | boolean | A fix asked for with POST …/fix: applied with fix/apply, which keeps the cases it re-ran. false for the check loop's own suggestion, taken by sending diff.after as the sentence. |
data.id | string | Required. |
data.job_id | string or null | |
data.language | string | Required. |
data.passage | object or null | |
data.passage.end | integer | Required. |
data.passage.start | integer | Required. |
data.refusal | object or null | |
data.refusal.class | string — one of nothing_observable, not_agent_control | Required. |
data.refusal.reason | string | Required. |
data.request_rule | object or null | |
data.request_rule.lever | string — one of effort_clamp, context_edit, prefix_guard | Required. |
data.request_rule.params | object | Required. |
data.sentence | string | Required. The intent policy. Empty while the drafting job still prepares it (busy is grounding and it holds no grounding yet): a sentence is served only once it is final. |
data.steer | string or null | |
data.validate | object or null | |
data.validate.example | object or null | |
data.validate.fires_on_every_action | boolean | Required. |
data.validate.never_fires | boolean | Required. |
Example response
Section titled “Example response”{ "data": { "busy": "string", "capability": "string", "cards": [ { "answer": { "choice": "accept", "fallback": "Ask", "question": "string", "values": [] }, "key": "string", "kind": "dictionary_values", "question": "string", "recommended": {} } ], "cases": [ {} ], "citation": { "edited": false, "entries": [ { "id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "title": "string", "url": "https://app.openlatch.ai/", "via": {} } ], "items": [ { "key": "string", "label": "string", "url": "https://app.openlatch.ai/" } ], "license_url": "https://app.openlatch.ai/", "preset_key": "string", "preset_title": "string", "rule_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "source_commit": "string", "source_date": "string", "source_sentence": "string", "version": 1 }, "confirmed": false, "deferred": { "class": "string", "fallback": "Ask" }, "dimension": "quality", "fallback": "Ask", "fix": { "attempts_left": 3, "available": false, "diff": { "after": "string", "before": "string" }, "fix_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "reason": "Never push to main without a review.", "requested": false }, "id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "job_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "language": "string", "passage": { "end": 3, "start": 3 }, "refusal": { "class": "nothing_observable", "reason": "Never push to main without a review." }, "request_rule": { "lever": "effort_clamp", "params": {} }, "sentence": "string", "steer": "string", "validate": { "example": "string", "fires_on_every_action": false, "never_fires": false } }}