Getting started¶
This guide takes you from a fresh InCheck account to your first grounded chat answer in under 10 minutes. Two paths, one endpoint, one proprietary engine.
What you need¶
- An InCheck Teams plan with admin access (admins mint API keys).
- For Unified mode only: one or more PDF / DOCX / PPTX / XLSX files to onboard into a Pod.
- Optional: Python 3.10+ for the SDK. Every step has a curl example.
1. Generate an API key¶
- Log into the InCheck admin console.
- Open Admin → API keys.
- Click Create new key, name it (e.g.
dev-laptop), copy the plaintext value — shown once only.
Keys look like incheck_<env>_<16hex>_<8hmac>. Each key is scoped to
one InCheck organization. The gateway derives a namespace from
your org's subdomain — lowercase letters/digits only — and rejects any
request that touches an org_id outside that namespace.
2. Install the SDK (Python users only)¶
Skip this section if you'll integrate with curl, fetch, or another HTTP client — the rest of the guide has tabs for both.
Requires Python 3.10+. The wheel + sdist are on PyPI at pypi.org/project/incheck.
3. Pick an environment¶
| Environment | Base URL | When to use |
|---|---|---|
production |
https://api.incheck.ai |
live customer traffic |
staging |
https://api-acceptance.incheck.ai |
integration testing |
For the rest of this guide we'll target staging.
Path A — EMS mode (no setup)¶
Ask an EMS protocol question and get an answer scoped to ALS/BLS and a US state. No Pod required.
curl -s -X POST "$INCHECK_BASE_URL/chat" \
-H "Authorization: Bearer $INCHECK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"conversation_id":"ems-1",
"user_id":"alice",
"streaming":false,
"content":"Adult dose of atropine for symptomatic bradycardia?",
"scope":"ALS",
"state":"Massachusetts"
}'
You'll get a Server-Sent-Event payload back:
That's everything for EMS mode.
Path B — Unified mode (chat with your documents)¶
Onboard files into a Pod (one Pod per org_id), wait for the
processing job to complete, then chat against the Pod.
1. Discover your namespace¶
The first segment of every org_id you create has to be your
namespace.
2. Onboard a Pod¶
A Pod is identified by an org_id like acme_dispatch. You can add
multiple files to the same Pod — they're queried together. The SDK
collapses the three-step presigned-upload flow into one call.
from incheck import Client
with Client(environment="staging") as client:
namespace = client.documents.list_orgs().filtered_by
org_id = f"{namespace}_dispatch"
status = client.documents.upload(
org_id,
files=["./dispatch_sop.pdf", "./policies.docx"],
wait=True,
timeout=600,
poll_interval=15,
)
print(status.status, status.progress.processed_pages, "pages")
NAMESPACE=$(curl -s "$INCHECK_BASE_URL/documents/orgs" \
-H "Authorization: Bearer $INCHECK_API_KEY" \
| python -c "import json,sys; print(json.load(sys.stdin)['filtered_by'])")
ORG_ID="${NAMESPACE}_dispatch"
FILE="./dispatch_sop.pdf"
FILENAME=$(basename "$FILE")
# 1. Initiate
INIT=$(curl -s -X POST "$INCHECK_BASE_URL/documents/initiate-upload" \
-H "Authorization: Bearer $INCHECK_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"org_id\":\"$ORG_ID\",\"filenames\":[\"$FILENAME\"]}")
JOB_ID=$(echo "$INIT" | python -c "import sys,json;print(json.load(sys.stdin)['job_id'])")
# 2. Upload to S3 with the presigned fields the gateway returned
# 3. Complete
curl -s -X POST "$INCHECK_BASE_URL/documents/complete-upload" \
-H "Authorization: Bearer $INCHECK_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"job_id\":\"$JOB_ID\",\"uploaded_files\":[\"$FILENAME\"]}"
# Poll until completed
curl -s "$INCHECK_BASE_URL/documents/job/$JOB_ID" \
-H "Authorization: Bearer $INCHECK_API_KEY"
Typical small-PDF onboarding completes in ~90–120 seconds. The job
status flows initiated → pending → processing → completed. The SDK
raises JobFailedError on failed and JobTimeoutError if you pass
timeout= and it elapses.
How does the grounding work?
The engine — extraction, structuring, grounding, retrieval-time decisioning — is our IP. It is not RAG; it materially outperforms off-the-shelf retrieval pipelines on accuracy and faithfulness. The public contract you see (upload, poll, query) is the whole surface. For deeper guarantees, custom evaluations, or a tuned pipeline for your domain, talk to us.
3. Inspect the Pod¶
docs = client.documents.list(org_id)
for d in docs.documents:
print(d.filename, d.size_bytes, d.download_url) # short-lived presigned GET
4. Chat against the Pod¶
Pass the same org_id to /chat. The model retrieves from your Pod
automatically.
curl -s -X POST "$INCHECK_BASE_URL/chat" \
-H "Authorization: Bearer $INCHECK_API_KEY" \
-H "Content-Type: application/json" \
-d "{\
\"conversation_id\":\"uni-1\",\
\"user_id\":\"alice\",\
\"org_id\":\"$ORG_ID\",\
\"streaming\":false,\
\"content\":\"What's our hazmat escalation policy?\",\
\"scope\":\"ALS\",\
\"state\":\"Massachusetts\"\
}"
Streaming¶
Either mode supports streaming. The SDK exposes it directly:
for chunk in client.chat.stream("Summarize the SOP.", org_id=org_id):
if chunk.content:
print(chunk.content, end="", flush=True)
Common errors¶
| HTTP | Detail | Fix |
|---|---|---|
401 |
Invalid API key |
Re-check INCHECK_API_KEY |
403 |
org_id must start with your namespace '<ns>_' |
Use <namespace>_<anything> |
400 |
org_id must match ^[a-z0-9]+(_[a-z0-9]+){1,9}$ |
2–10 lowercase alnum segments joined by _ |
403 |
Your organization is not configured for the customer API |
Your org's subdomain didn't derive to a namespace — contact us |
400 |
Missing fields, with a mode hint inline | Add the missing fields the error lists |
429 |
Rate limited | Back off using Retry-After |
Go deeper with the Python SDK → Browse the HTTP API reference →