Sandbox / Test mode
Test your integration without touching production
CBCTHub gives you an isolated sandbox to validate your integration without touching production. Test keys are identified by the cbct_test_ prefix (vs cbct_live_) and everything you create with them lives in a parallel universe: it does not consume storage, does not count against your exam limit, and the webhooks it fires are separate from production ones.
When to use sandbox
- While developing the integration for the first time.
- In your CI / staging pipeline for automated end-to-end tests.
- Before running a change in production: replay it in sandbox to verify.
- For demos or training without polluting your real data.
How to create a test key
In the dashboard go to Settings → API. Switch to the Sandbox tab, type a name and click Create test key. The key starts with cbct_test_ and shows up tagged with an orange TEST badge in the list.
# Una key de test luce así:
Authorization: Bearer cbct_test_z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4What exactly gets isolated
- Data: exams created with a test key carry is_test=true. A live key never sees them; a test key only sees its own. Requesting an exam_id from the other mode returns 404.
- Storage: test files do NOT count against your storage_used_bytes. You can upload as much as you need to test.
- Exam count: test exams do NOT increment your exam_count. Your plan quota is preserved.
- Rate limit: test keys have their own bucket of 1000 req/h, independent of plan. It does not consume your production quota.
- Webhooks: by default subscriptions only receive live events. To receive sandbox events you must enable the enabled_test flag on the subscription.
How to identify the mode in the payload
All webhook payloads include a boolean livemode field (Stripe-style): true for production, false for sandbox. Your integration can branch logic on this flag without inspecting the URL or maintaining separate subscriptions.
{
"id": "evt_9z8y7x6w5v",
"type": "exam.confirmed",
"created_at": "2026-06-23T14:33:01Z",
"livemode": false,
"data": {
"exam_id": "exm_test_abc123",
"status": "ready",
...
}
}Configure webhooks for sandbox
Each webhook subscription has two flags: enabled_live and enabled_test. Default is enabled_live=true and enabled_test=false. You can enable test on an existing subscription (PATCH) or create a new subscription dedicated to sandbox.
# Crear una subscription dedicada solo a sandbox
curl -X POST https://cbcthub.com/api/v1/webhooks \
-H "Authorization: Bearer $CBCTHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://staging.miclinica.com/webhooks/cbcthub",
"events": ["exam.confirmed", "report.signed"],
"description": "Sandbox staging",
"enabled_live": false,
"enabled_test": true
}'
# Activar test mode en una subscription existente
curl -X PATCH "https://cbcthub.com/api/v1/webhooks/$SUB_ID" \
-H "Authorization: Bearer $CBCTHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "enabled_test": true }'Recommended workflow
- Generate a cbct_test_* key and store it in the CBCTHUB_API_KEY_TEST env var of your staging environment.
- Create a webhook subscription with enabled_live=false and enabled_test=true pointing to your staging URL.
- In your CI pipeline run the end-to-end flow with the test key. You receive events just like production but with livemode: false.
- When everything passes, repeat with the cbct_live_* key in production.
Quick test with curl
# Verifica que la key de test funciona y aparece en sandbox
curl https://cbcthub.com/api/v1/me \
-H "Authorization: Bearer cbct_test_..."
# Crea un examen en sandbox (no descuenta storage)
curl -X POST https://cbcthub.com/api/v1/exams \
-H "Authorization: Bearer cbct_test_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Test exam",
"patient_name": "Sandbox Patient",
"files": [{ "name": "ct.dcm", "size": 1024 }]
}'
# Lista solo lo creado en sandbox (los exams live no aparecen)
curl https://cbcthub.com/api/v1/exams \
-H "Authorization: Bearer cbct_test_..."Cleaning up test data
Sandbox exams stay in the database until you explicitly delete them with DELETE /api/v1/exams/{id}. They do not consume storage so cleanup is usually not needed, but you can do it to keep your sandbox listing tidy.