Sandbox quickstart

Most recipes in this section assume you already have a Huli organization and an admin who can mint you a bearer token in Practice Settings. A sandbox is the same idea, pointed at synthetic data: a dedicated organization pre-seeded with fabricated patients, appointments, encounters, and observations, so you can build and test your integration before it touches anything that looks like production.

A sandbox is created for you by someone with a Huli account — an org admin at the clinic you're integrating with, or your Huli contact. There is no anonymous self-serve provisioning endpoint: the person creating the sandbox does it from inside HuliPractice, and hands you the credential through a one-time link. Your side of the flow needs nothing but that link and an HTTP client.

Audience

You're an external developer evaluating the Huli Public FHIR API, building a proof of concept, or developing an integration that isn't ready for real patient data. You have a contact at Huli or at a clinic who can create the sandbox for you.

You'll need

  • Someone with an admin-role HuliPractice login willing to create the sandbox — see the admin's side below, which you can forward to them verbatim.
  • The one-time share link they send you after creating it.
  • curl (or any HTTP client). The huli CLI works too — the credential is a plain bearer token, so --token is all it needs.

End state

A dedicated sandbox organization seeded with fabricated clinical data; a bearer API key bound to that org and to nothing else, valid for 14 days; and one successful GET against the same FHIR R4 surface every production integration uses.

The admin's side: creating a sandbox

If you're the org admin or Huli operator creating the sandbox for a developer: a sandbox is always attached to one production API key, from Practice Settings → Integrations.

  1. Creating a new integration? Leave "Generar un entorno de pruebas (recomendado)" checked in the create wizard — the production key and its paired sandbox are minted together and disclosed in one share link. For an existing key, open the key row's menu and choose "Gestionar entorno de pruebas" (Manage sandbox), then create the sandbox from there.
  2. The sandbox's identity is derived from the production key itself — there is no email or name to fill in. Managing the sandbox again for the same key reuses the existing sandbox organization (and its data); refreshing just mints a fresh key — it never creates a duplicate org.
  3. On success you get a one-time share link (valid for 24 hours, single use) containing the developer's bearer credential. Send that link — not a pasted token — to the developer over a reasonably private channel. The secret itself is only ever revealed on the share page, exactly once.

The sandbox organization is created and seeded at that moment — fabricated patients, practitioners, appointments, encounters, and observations, referentially consistent, zero real data. The minted key is bound to the sandbox org and can never reach any other organization's data: the credential is the boundary.

The developer's side

The link your contact sends looks like https://<practice-host>/api-keys/share/…. It works once, then self-destructs; the same page shows the API base URL. Store the bearer token in a secrets manager or environment variable immediately — nobody, including the admin who created it, can view it again. If you lose it, ask your contact to refresh the sandbox from the key's Gestionar entorno de pruebas dialog: you'll get a new key on the same organization.

2. Make your first call

The sandbox key is an ordinary bearer credential on the same FHIR R4 surface as production — no separate sandbox auth mode, no token-exchange handshake:

export HULI_SANDBOX_TOKEN="<the token from the share page>"

curl "https://api.huli.ai/fhir/R4/Patient?_count=5" \
  -H "Authorization: Bearer ${HULI_SANDBOX_TOKEN}" \
  -H "Accept: application/fhir+json"

A 200 OK returns the same FHIR Bundle shape as Start — just backed by fabricated data instead of a clinic's real records.

Or run it right here — paste your sandbox token into the playground token bar above the recipes nav (or on this page's Run button, the first time you use one) and press Run:

GET/fhir/R4/Patient?_count=5

Set your sandbox token above to run this request.

With the huli CLI, pass the token directly:

huli --token "${HULI_SANDBOX_TOKEN}" fhir patient search --count 5

The sandbox indicator

There's no request-level "sandbox mode" flag to remember or forget — the mode lives in the credential. A sandbox key can only ever resolve to its own sandbox org, so there's no header or query param that could accidentally point it at real data. Every response served by a sandbox key carries two identifying signals — one on the transport, one inside the payload:

X-Huli-Mode: sandbox
{
  "resourceType": "Patient",
  "meta": {
    "tag": [
      {
        "system": "https://huli.io/tags",
        "code": "sandbox",
        "display": "Synthetic sandbox data"
      }
    ]
  }
}

The meta.tag is stamped on every resource a sandbox key reads or writes — single resources, search Bundles, and each Bundle entry alike — so even data copied out of a response (into a fixture, a demo, a bug report) stays self-identifying as synthetic. Use both as belt-and-suspenders checks in your own logs or tests: neither should ever appear on a response your production key receives, and both should always appear on a sandbox key's responses.

Limits and expiry

Sandbox keys carry ceilings a production key doesn't:

CeilingDefaultEnforcement
Rate limit60 req/minSame 1-minute sliding window as every other key.
Volume cap (lifetime)10,000 requestsCounted per request; never resets on its own.
Key expiry14 daysStamped at minting; an expired key is rejected. The org and its data persist.
Keys per sandbox5Each sandbox-key refresh mints a new key on the same org, up to this cap.

Only the credential expires — the sandbox organization and its seeded data are never deleted. When a key lapses (or you simply want a fresh one), your contact opens the production key's Gestionar entorno de pruebas dialog and refreshes the sandbox key: same org, same data, new key, new one-time link.

What to verify

  • The share link opened exactly once and showed a bearer token plus the base URL.
  • GET /fhir/R4/Patient?_count=5 with the token returns a 200 with a Bundle, not an OperationOutcome.
  • The response headers include X-Huli-Mode: sandbox, and each resource carries the meta.tag with system: "https://huli.io/tags" and code: "sandbox".

What can go wrong

401 Unauthorized — the token is wrong, or the key expired (14 days after

minting). Ask your contact to refresh the sandbox key from the production key's Manage-sandbox dialog — you'll get a fresh key on the same organization.

429 Too Many Requests HPB-00105 — the per-key request-rate limit (see

Rate Limiting); read Retry-After.

429 Too Many Requests HPB-00121 — the lifetime volume cap is exhausted, not the

per-minute rate. Retry-After will not help here; resetting a sandbox key's volume counter is operator-only — reach out to your Huli contact.

The share link says it was already used or expired — share links are single-use with a 24-hour window. Ask your contact to refresh the sandbox key from the production key's Manage-sandbox dialog; a new key and a new link are minted, and the existing org and data are reused.

Graduating to production

When your integration is ready for real patient data, the path is the standard partner one: the clinic's admin mints you a production key from the same Practice Settings surface — see Creating and sharing an API key — or your Huli contact walks you through the commercial onboarding. Your sandbox keeps working alongside it; it's a separate organization, so nothing you built against it needs to change.

Next recipes