Demo Runbook (Source)¶
Airfree Cloud ↔ HostivaPro Sandbox — Demo Runbook (Checklist)¶
Goal: In ≤ 60 minutes, demo Domain Search → Order → Checkout from Airfree Cloud using HostivaPro Sandbox API.
This runbook is intentionally short and copy/paste friendly.
0) What you need (5 minutes)¶
A) API Base (Hostiva Core)¶
- Base URL:
https://core.hostiva.quantumdevlabs.com/api/v1
B) Tenant Slug¶
Each reseller has its own tenant slug:
- Airfree Cloud → airfree (or hostiva if you’re still running single-tenant during demo)
- Celteck Cloud → celteck
- Default/dev tenant → hostiva
C) Sandbox Developer API Key¶
You need a key starting with sbx_...
Security rule: Do NOT expose the key in browser JS.
Airfree backend should call Hostiva (server-to-server), then return clean results to the frontend.
1) Define environment variables (copy/paste)¶
Run on any machine with curl + jq (Linux server, WSL, macOS).
BASE="https://core.hostiva.quantumdevlabs.com/api/v1"
TENANT="airfree" # set to your reseller tenant slug (airfree/celteck/hostiva)
KEY="sbx_REPLACE_WITH_YOUR_KEY"
Quick sanity check:
echo "$BASE" && echo "$TENANT" && echo "${KEY:0:8}"
2) Sandbox Domain Search (✅ must work first)¶
Request¶
curl -sk "$BASE/sandbox/domains/search" -H "Accept: application/json" -H "Content-Type: application/json" -H "X-Tenant: $TENANT" -H "Authorization: Bearer $KEY" --data-raw '{"domain":"example.com"}' | jq .
Expected (example)¶
{
"query": "example.com",
"status": "available",
"tld": "com",
"price": { "currency": "USD", "register": 9.99, "renew": 11.99, "transfer": 9.99 },
"meta": { "source": "hostiva-sandbox" }
}
Common failures¶
- 401 Unauthorized (developer api key invalid)
→ wrong key, wrong tenant, or key not stored/hashed with the current hashing mode. - 403 Forbidden (scope permission denied)
→ enable permissionsandbox.searchfor that key in Developer Keys UI.
3) Sandbox Order (reserve intent)¶
This step creates an “order intent” (a draft order) for the domain.
Request¶
curl -sk "$BASE/sandbox/domains/order" -H "Accept: application/json" -H "Content-Type: application/json" -H "X-Tenant: $TENANT" -H "Authorization: Bearer $KEY" --data-raw '{
"domain": "example.com",
"years": 1,
"contact": {
"first_name": "Valentine",
"last_name": "Onyemachi",
"email": "dev@airfreeng.com",
"phone": "+2348000000000",
"country": "NG"
}
}' | jq .
Expected (shape)¶
You should receive something like:
- order_id or order_ref
- domain
- state like draft / pending_checkout
- pricing totals
Your exact response fields depend on your controller implementation, but the key is: order intent is created and returned.
4) Sandbox Checkout (finalize order)¶
This simulates a “paid” completion in Sandbox and returns a final state.
Request (example — adjust to your response fields)¶
If order returned order_id, use it here:
ORDER_ID="REPLACE_WITH_ORDER_ID"
curl -sk "$BASE/sandbox/domains/checkout" -H "Accept: application/json" -H "Content-Type: application/json" -H "X-Tenant: $TENANT" -H "Authorization: Bearer $KEY" --data-raw "{
"order_id": "$ORDER_ID",
"payment": { "method": "sandbox", "reference": "demo_$(date +%s)" }
}" | jq .
Expected (shape)¶
statuslikecompleteddomaininfo- maybe
provisioning_job_idif your SLE hooks in
5) “Happy path” demo flow for Airfree UI (what to show management)¶
1) Search a domain that is available: example.com
2) Show price box + checkout summary
3) Click “Order” (calls order)
4) Click “Complete Checkout” (calls checkout)
5) Show confirmation “Domain order completed (Sandbox)”
6) Optionally show “Order ID / Reference”
6) Test scenarios (fast but thorough)¶
A) Search scenarios¶
- Available domain:
example.com - Taken domain:
google.com(your mock can forcetaken) - Invalid domain format:
example(no TLD) → expect422 - Unsupported TLD:
example.invalidtld→ expect422orunsupported
B) Permission scenarios¶
Use a key without search:
- Expect 403 with:
{ "message":"Forbidden (scope permission denied).", "required":"search" }
C) Tenant isolation scenarios¶
Use Airfree key with Celteck tenant: - Expect 401/403 (depends on your policy) - This proves tenant isolation works
D) Rate limiting scenarios¶
Spam search in a loop: - Eventually expect 429 “Rate limit exceeded”
7) Troubleshooting cheatsheet¶
“parse error: Invalid numeric literal” from jq¶
You likely wrote the curl as a single line incorrectly. Fix: Use the multiline version exactly as shown.
401 “developer api key invalid”¶
- Confirm you’re calling the core host:
core.hostiva.quantumdevlabs.com - Confirm headers include both:
Authorization: Bearer $KEYX-Tenant: $TENANT- Confirm DB has a row with correct
tenant_slug,scope=sandbox, and it is active
403 “scope permission denied”¶
- Set the permission in UI:
sandbox.search/sandbox.order/sandbox.checkout
8) Where devs manage keys & permissions (UI)¶
Developer portal:
- https://core.hostiva.quantumdevlabs.com/developer/keys
Per key:
- Scope: sandbox / sandbox-proxy / live
- Permissions:
- sandbox: search, order, checkout
- sandbox-proxy: check
- live: check, smart-search
9) Airfree integration architecture (recommended)¶
Frontend (Airfree Cloud UI) - Search form + results - Checkout sidebar
Backend (Airfree API)
- Calls Hostiva Sandbox API
- Stores order_id + statuses
- Never exposes Hostiva dev key to browser
HostivaPro Core - Does auth, permission enforcement, rate limiting, usage logging
10) Quick “ready to demo” checklist¶
- [ ] Sandbox key created for tenant
airfree - [ ] Key has permissions:
search,order,checkout - [ ] Search endpoint returns JSON for example.com
- [ ] Order endpoint returns an order identifier
- [ ] Checkout endpoint returns completed status
- [ ] Airfree UI calls Airfree backend (not Hostiva directly)
- [ ] Demo flow rehearsed once end-to-end
If anything fails: copy/paste the exact curl + output and we’ll fix in minutes.