Skip to main content

Use the App API and SDKs

Use AgentData behind your application's own interface. Your application submits a case, retrieves the result, and lets the user approve, reject or correct it. AgentData retains the submitted input and original prediction alongside the user's decision.

This guide covers consuming a released App from your application backend. Current comparison Apps accept typed snapshots with declared columns, keys and rows. Ask your AgentData contact for the HTTPS gateway address, App key, major version, client credential, and operations enabled for your application. Separately enabled direct capabilities can extract uploaded documents and run named source queries. These operations do not change the comparison case format.

Download the SDKs​

Download the Python and TypeScript SDK bundle. It includes the current external API specification and a SHA-256 manifest.

Individual files: Python client, TypeScript client, API specification, checksums.

Python requires Python 3.11 or later and uses the standard library. TypeScript uses fetch and Web Crypto in your server runtime. Both clients accept your gateway address, credential provider, timeout and response-size limit as configuration.

Keep client credentials in your application backend or secret store. Your browser UI calls your own backend; it must not contain the AgentData credential. Use a fresh signed user proof for each authenticated user when your client uses individual user ownership. The SDK's subject callback supplies this proof from your identity backend.

Connect your application​

An API key is sent as Authorization: Bearer <credential>. If you received a confidential OAuth client secret instead, exchange it at /app-api/oauth/token using form fields:

grant_type=client_credentials
client_id=<your registered application ID>
client_secret=<your confidential client secret>

Use the returned short-lived access token as the bearer credential and refresh it before expiry. An optional scope requests a subset of your application's permissions.

Cases can be owned by the whole registered application or by individual verified users. With individual ownership, include X-AgentData-Subject; a plain email or username is not accepted as proof. Your identity integration supplies the client-bound signed proof, and you must use the proof for the current user.

Retrieve your App's contract from /app-api/apps/{app_key}/v{major}/openapi.json. It lists the operations and request formats available for that released major. Use that contract when integrating a specific App; the downloadable generic specification describes the current external API surface.

Submit a comparison case​

A typed snapshot declares its grain, primary key, column types, rows and whether coverage is complete. Decimal values use strings to preserve their precision. Use the schema in your App contract to validate your snapshot.

import json
import os
from agentdata_client import AgentDataClient

api = AgentDataClient(
base_url=os.environ["DATAAPI_ORIGIN"],
credential=lambda: os.environ["AGENTDATA_API_KEY"],
timeout_seconds=float(os.environ["AGENTDATA_TIMEOUT_SECONDS"]),
max_response_bytes=int(os.environ["AGENTDATA_MAX_RESPONSE_BYTES"]),
)
with open(os.environ["SNAPSHOT_FILE"], encoding="utf-8") as source:
snapshot = json.load(source)
case = api.submit(
app_key=os.environ["AGENTDATA_APP_KEY"],
major=int(os.environ["AGENTDATA_APP_MAJOR"]),
idempotency_key=os.environ["CASE_REQUEST_KEY"],
body={"input": {"snapshot": snapshot}},
)
import {AgentDataClient, type Snapshot} from './agentdata_client';

const api = new AgentDataClient({
baseUrl: config.dataApiOrigin,
credential: () => secrets.agentDataApiKey,
timeoutMilliseconds: config.timeoutMilliseconds,
maxResponseBytes: config.maxResponseBytes,
});
const snapshot: Snapshot = await loadApplicationSnapshot();
const caseResult = await api.submit({
app_key: config.appKey, major: config.appMajor,
idempotency_key: applicationRequestId, body: {input: {snapshot}},
});

Use one stable idempotency key per business submission. Retrying the same key and input returns the same case. Reusing it for a different input returns a conflict. A replay does not create or charge another case.

Retrieve your results​

Use the returned case_id to read the case:

result = api.read(
app_key=case["app_key"], major=case["major_version"], case_id=case["case_id"],
)

While processing, the case is queued or running. An equal comparison is completed; differences or incomplete coverage produce an exception that needs review. A failed case includes a safe error code.

The response includes the original input, prediction, released version, current revision, and a separate decision when reviewed. Draft changes do not alter the version used for an existing case.

List your cases with api.listing(...). Pass the returned next cursor as after to retrieve another page. api.history(...) shows the case's retained submission, result and review history. Your application and user permissions apply to every read.

Cancel a queued or running case with api.cancel(...) and its expected_revision. Retry a failed case with api.retry(...), using its current revision and a valid credential. A retry preserves the original input and App version.

Review a case​

Send the case's current revision with your decision:

reviewed = api.decide(
app_key=result["app_key"], major=result["major_version"],
case_id=result["case_id"],
body={
"expected_revision": result["revision"],
"decision": "approve",
"reason": "Checked against the original record",
},
)

Use reject to reject the result, or correct with a correction shaped as {"snapshot":...}. AgentData evaluates the corrected snapshot separately; the original input and prediction remain available. Reviewing requires your application's decision permission and ownership of the case.

A correction may include golden_consent:true if the user explicitly agrees to contribute it as a training candidate. Consent creates a candidate pending review; it does not automatically change an evaluation dataset. Retrieve it with api.golden(...).

If another action changed the case, a stale revision returns HTTP 409. Reload the case and show the updated result to the user before submitting another decision.

Other available operations​

Your application's permissions determine which direct capabilities are available:

SDK methodWhat it does
compareCompares two caller-supplied typed snapshots.
extractExtracts fields and evidence from an uploaded PDF, PNG or JPEG using your enabled document type.
resolvePreviews exact PO candidates in a caller-supplied snapshot. It does not reserve funds or modify a purchase order.
saved_queryRuns a named query supplied by the released App, such as your case counts or case list.
queryRuns a named App query through the direct capability endpoint.
source_queryRuns an enabled named source read with typed parameters and your configured identity integration.
notifyRequests delivery of an existing owned case event to your application's registered receiver.

Named queries do not accept arbitrary SQL or a source connection. The App's contract provides their names and available inputs.

Extract an uploaded document​

Ask your contact for the enabled document_type name and its supported file formats. Send the original file's bytes as Base64; a local path or download URL is not accepted.

import base64

with open(os.environ["DOCUMENT_FILE"], "rb") as source:
content = base64.b64encode(source.read()).decode("ascii")
extracted = api.extract(body={
"document_type": os.environ["AGENTDATA_DOCUMENT_TYPE"],
"mime_type": os.environ["DOCUMENT_MIME_TYPE"],
"content_base64": content,
"inputs": {},
})

Supply only the runtime inputs declared for your document type. The response contains scalar fields, repeated rows, evidence quotes and page coordinates, issues, a content-based document identifier, and usage. Review field states and findings before using a value. complete:false indicates incomplete processing; missing values must not be treated as proven absence. Extraction returns a pending decision and does not approve documents automatically or create a comparison case.

Requests and files must fit the enabled upload and processing limits. usage.llm_tokens contains measured provider tokens. If provider usage cannot be measured after a failure, llm_tokens_estimated records the conservative estimate separately and tokens_exact is false.

Read a named source query​

Your contact supplies the query name and its parameter contract. Call api.source_query(body={"query_key": query_name, "parameters": parameter_values}). The response contains columns and rows; no raw query text or connection details are accepted from the caller.

Individual-user source access also requires the identity-session handle supplied by your organization's identity integration as identity_session. It must belong to the same verified user represented by the signed proof. Your backend obtains and refreshes that handle; copying another user's handle does not grant access. Missing, expired or changed source authorization prevents results from being returned.

Use the reference review interfaces​

When your application owner provides the reference interface, sign in through your organization gateway and select DJ review or Insurance review. Choose the typed statement or claim JSON file, or use the clearly labeled synthetic example, then select Start review.

Open a case in the review queue to see its original records and comparison findings. Completed comparisons and exceptions can be approved or rejected with a reason. To correct a record, upload corrected JSON and select Save correction. The training-example consent checkbox is optional and starts unchecked. The original input and prediction remain available after a correction.

These minimal reference interfaces compare typed records against the published reference. Settlement, coverage adjudication and deductible accounting depend on the relevant approved application rules.

Receive case notifications​

If notifications are enabled for your application, its receiver gets case.created, case.exception and case.closed events. The body contains event, App, version and case identifiers, the case revision, and the occurrence time. It contains no documents, extracted fields, user identities, credentials or financial values. Read the case through the authenticated API to retrieve its result.

Verify the signature against the exact received bytes before accepting an event. Use X-AgentData-Timestamp, X-AgentData-Event and X-AgentData-Signature with the SDK verification helper:

from agentdata_client import verify_webhook

valid = verify_webhook(
secret=receiver_secret,
timestamp=request_headers["X-AgentData-Timestamp"],
event_id=request_headers["X-AgentData-Event"],
body=raw_request_body,
signature=request_headers["X-AgentData-Signature"],
now=current_unix_time,
replay_seconds=receiver_replay_window,
)

The TypeScript SDK supplies verifyWebhook with the same inputs. Persist processed event IDs and deduplicate repeated delivery. Return a 2xx response after durable acceptance. Delivery may be retried, so receiving the same event more than once is expected.

Handle limits and errors​

HTTP statusWhat to do
401Refresh the credential or current user's signed proof.
402Your workspace has no LLM balance available; contact your application owner.
403Check that the requested operation is enabled for your client and App major.
404Check the identifier and current application/user ownership.
409Reload the current case revision, or check that the operation exists in your App's contract.
422Correct the request against the contract schema.
429Wait for Retry-After before retrying.
503The requested runtime or operation is unavailable; contact your AgentData support team.

The SDK exposes HTTP status and Retry-After through ApiError. It does not automatically retry writes. Reuse the submission idempotency key after a timeout to avoid a duplicate case.