TrueRoute Developers

Quickstart

Everything here runs against the sandbox with synthetic data. The key and secrets below are visibly fake placeholders: replace them with the ones issued to you, and never paste a real key or secret into a ticket, a chat or a log.

export TR_BASE="https://sandbox.trueroute.health"
export TR_API_KEY="tr_sandbox_EXAMPLE_KEY_DO_NOT_USE"
export TR_SIGNING_SECRET="trsec_EXAMPLE_SECRET_DO_NOT_USE"

1. Is the API enabled here?

curl -s "$TR_BASE/health/enterprise"

No credential needed. It reports whether the deployment has the partner API mounted. If it is not mounted, every partner path answers 404.

2. A GET: bearer only

curl -s "$TR_BASE/v1/integrations/catalog" \
  -H "Authorization: Bearer $TR_API_KEY"

curl -s "$TR_BASE/v1/modules/availability?clinicId=<YOUR_CLINIC_ID>" \
  -H "Authorization: Bearer $TR_API_KEY"

GETs are never signed. catalog:read and modules:read are the scopes.

3. A signed POST, unkeyed form (a quote)

The quote endpoint takes no Idempotency-Key, so it is signed over {t}.{rawBody}. Write the body to a file once and send that file, so the bytes you sign are the bytes you send.

printf '%s' '{"patient":{"externalPatientId":"synthetic-patient-one","shippingState":"TX","dateOfBirth":"1980-01-01"},"provider":{"npi":"<SYNCED_PRESCRIBER_NPI>"},"productId":"<PACKAGE_ID_FROM_CATALOG>","quantity":1,"orderType":"patient_specific","shippingService":"ground"}' > quote.json
T=$(date +%s)
SIG=$(printf '%s.%s' "$T" "$(cat quote.json)" \
  | openssl dgst -sha256 -hmac "$TR_SIGNING_SECRET" -hex | sed 's/^.* //')
curl -s "$TR_BASE/v1/integrations/quotes" \
  -H "Authorization: Bearer $TR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-TrueRoute-Signature: t=$T,v1=$SIG" \
  --data-binary @quote.json

Two details keep the signed bytes and the sent bytes identical: printf '%s' writes the body with no trailing newline, and --data-binary sends the file unchanged (-d strips newlines).

4. A signed POST, keyed form

Endpoints that require an Idempotency-Key (marked in the reference) sign TRv1.{t}.{keyLength}.{key}.{rawBody}:

KEY=$(uuidgen | tr 'A-Z' 'a-z')   # one per logical operation; persist it
printf '%s' '<REQUEST_JSON>' > body.json
T=$(date +%s)
SIG=$(printf 'TRv1.%s.%s.%s.%s' "$T" "${#KEY}" "$KEY" "$(cat body.json)" \
  | openssl dgst -sha256 -hmac "$TR_SIGNING_SECRET" -hex | sed 's/^.* //')
curl -s "$TR_BASE/v1/integrations/regimen-quotes" \
  -H "Authorization: Bearer $TR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" \
  -H "X-TrueRoute-Signature: t=$T,v1=$SIG" \
  --data-binary @body.json

Retrying after a timeout: send the SAME key and the SAME body.json with a fresh t and signature. You get the stored answer (Idempotent-Replay: true), never a second order.

5. When something is refused

You seeDo
404 on every paththe deployment has not enabled the partner API: check /health/enterprise
authentication_failed (401)check the key, the signing secret, keyed vs unkeyed form, and that you signed the exact bytes you sent
signature_expired (401)your clock is off by more than the window: sync NTP and re-sign
environment_mismatch (403)a sandbox key on production or the reverse
insufficient_scope (403)ask TrueRoute for the scope; never reuse another credential
request_in_flight (409)the same key is still running: wait, then retry the same key and bytes
idempotency_key_reuse (422)you changed the body under an old key: send the original bytes, or a new key for a new operation
rate_limited (429)wait Retry-After seconds

Every code: errors.