The ask call
POST https://api.datagoat.io/v1/ask, or the dg_ask tool over MCP. It is the one call: a
record, questions and cases go in, and one answer per question comes back. This page is the
reference. The ideas behind it are in The record, Questions and
Answers.
Request
{
"data": {"dataset_id": "sample:saas_churn"},
"entity_column": "customer_id",
"subject_kind": "org",
"questions": {
"churn": {"type": "yesno", "outcome_column": "churned", "outcome_is_desirable": false},
"risk": {"type": "score", "outcome_column": "churned", "outcome_is_desirable": false}
},
"cases": {"ids": ["cust_0001"]},
"idempotency_key": "3f1c…"
}
| Field | Required | |
|---|---|---|
data |
yes | the record: exactly one of dataset_id, rows, csv, fetch_url (with optional fetch_headers). The record |
entity_column |
yes | the column that names each case |
subject_kind |
yes | person, org, object, event or other |
questions |
yes | 1 to 8 questions, keyed by id. Questions |
cases |
for yesno, score, choice |
{"ids": [...]} or {"rows": [...]}, up to 10,000. Omit to rank the whole record. |
time_column |
with a shape; optional for a table | the time column; orders rows, so cases by id read each case's latest row |
shape |
no | how to read a record that isn't one row per case. Shapes |
acknowledge_decision_support |
when subject_kind is person |
must be true |
band |
no | adds band, band_reason and max_autonomy to each case |
idempotency_key |
no | a retry with the same key, within 24 hours, returns the first answer and never fits or bills twice |
Question fields
| Field | Types | |
|---|---|---|
type |
all | yesno, score, choice or rank |
outcome_column |
all but choice with option_outcomes |
the yes/no column to learn |
outcome_is_desirable |
all; required for choice |
whether the outcome is wanted |
positive_values |
all | the values of the outcome column that mean yes |
refit_of |
all | the model_ref of an earlier answer, for drift |
levels, cuts |
score |
score |
option_column, options or option_outcomes |
choice |
choice |
top_k |
rank |
1 to 1,000, default 20 |
Response
200 with {"status": "done", "answers": {…}, "fits_run", "billable_decisions", …}, or 202
with {"status": "pending", "task_id", "retry_after_ms"} while a first fit runs. Poll dg_poll
(POST /v1/poll) with the task_id. Every field is described in Answers.
Errors
Errors are RFC 9457 problems
(application/problem+json) with code, detail, remedy, and field when an argument is at
fault. A refusal is not an error: it is an answer with state: "refused".
| Code | Field | Fix |
|---|---|---|
invalid_request |
the field named | The request doesn't match the schema. The detail says how. |
entity_column_missing, time_column_missing, outcome_column_missing, option_column_missing |
the column field | Name a column of the record. The remedy lists them. |
positive_values_required |
questions.<id>.positive_values |
Say which values of the outcome column mean yes. |
positive_values_differ |
questions.<id>.positive_values |
The option_outcomes columns use different yes values. Pass the ones they share. |
outcome_not_binary, outcome_constant |
questions.<id>.outcome_column |
Name a yes/no column that holds both yes and no. |
unknown_case_id |
cases.ids |
Send ids that appear in the entity column, or send the rows. |
row_not_scoreable |
cases |
Send every column the model uses, with the same types. |
unknown_dataset |
data.dataset_id |
The dataset was deleted (24 hours after last use) or isn't in this workspace. Store it again. |
shape_invalid, shape_empty |
shape |
Shapes |
test_key_samples_only |
A test key works on the samples only. Create a live key at datagoat.io/keys. | |
scope_required |
Reporting outcomes and attesting need a key with "Can report outcomes", or an OAuth sign-in. | |
lever_token_invalid, post_value_unreadable |
lever_token, post_value |
(dg_attest) Pass the token exactly as received, and the new value in the record's units. |
dataset_sealed |
dataset_id |
(dg_add_dataset) The dataset has been asked about, so it takes no more rows. Store a new one. |
idempotency_conflict |
idempotency_key |
The key was used for a different request. Use a new one. |
engine_timeout, engine_unavailable |
Retry; the SDKs mark these retryable. |
Cost
One decision per answered case, $0.00002 each ($20 per million). A fit is $0.01 after 1,000 free
each month. Refusals, not_yet, declined cases and the samples are free.
Answers.