Skip to content

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

  1. Log into the InCheck admin console.
  2. Open Admin → API keys.
  3. Click Create new key, name it (e.g. dev-laptop), copy the plaintext value — shown once only.
export INCHECK_API_KEY="incheck_prod_..."

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.

uv add incheck
pip install incheck

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
from incheck import Client

# While building / smoke-testing:
client = Client(environment="staging")

# In production:
# client = Client()
export INCHECK_BASE_URL="https://api-acceptance.incheck.ai"   # staging
# export INCHECK_BASE_URL="https://api.incheck.ai"            # prod

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.

from incheck import Client

with Client(environment="staging") as client:
    reply = client.chat.send(
        "Adult dose of atropine for symptomatic bradycardia?",
        scope="ALS",
        state="Massachusetts",
    )
    print(reply.content)
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:

data: {"content": "1.0 mg IV/IO every 3-5 min, up to 3 mg total..."}
data: {"type": "complete"}

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.

with Client(environment="staging") as client:
    info = client.documents.list_orgs()
    print("namespace:", info.filtered_by)
# namespace: acme
curl -s "$INCHECK_BASE_URL/documents/orgs" \
  -H "Authorization: Bearer $INCHECK_API_KEY"
# {"org_ids":[...],"total_count":...,"filtered_by":"acme"}

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.

reply = client.chat.send(
    "What's our hazmat escalation policy?",
    org_id=org_id,
    user_id="alice@hospital.org",
)
print(reply.content)
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 →