Gatetrol API - v1
REST API for inbound classification, autoreply, voice receptionist, and outbound webhook delivery. All endpoints respond with application/json unless noted.
Authentication
Every protected endpoint accepts an API key issued from the dashboard at /app/api_keys.php.
Authorization: Bearer gtl_live_<your_key>
Alternative headers: X-Gatetrol-Key: gtl_live_…, or query param ?api_key=… (discouraged - leaks via logs).
Browser dashboard auth: session cookie set by the magic-link flow.
Endpoints
GET /v1/health.php
Liveness + DB ping. Public, no auth.
GET /v1/settings.php
Return the per-tenant settings (timezone, business hours, urgency keywords, VIP list, autoreply templates, digest config, voice greeting). Defaults are filled in for null fields.
PUT /v1/settings.php
Update one or more fields. Send JSON body with whitelisted keys: timezone, business_hours_json, urgency_keywords, vip_emails, personal_contacts, autoreply_customer, autoreply_unknown, autoreply_after_hours, forward_personal_to, digest_enabled, digest_local_time, alert_channel, alert_email, paused_until, voice_business_name, voice_greeting_text.
GET /v1/classifications/list.php
List classified messages. Query params:
class- urgent | customer | routine | personal | spam | unknownchannel- email | sms | phoneneeds_review- 1 to filter unresolved/review-flaggedsince- ISO date or datetimecursor- last id from previous page (descending)limit- 1–200 (default 50)
Returns { ok, data: [...], next_cursor, count }.
POST /v1/classifications/resolve.php
Mark a classification resolved. Body: { "id": 123, "by": "optional label" }.
POST /v1/classifications/draft_reply.php
Get an AI-drafted reply using the tenant's KB context. Body: { "id": 123, "instructions": "optional extra guidance" }. Returns { ok, draft }.
POST /v1/classifications/sms_reply.php
Send an SMS reply to the sender of an SMS classification, via the tenant's configured carrier. Body: { "id": 123, "body": "Your reply" }. Marks the original resolved.
Canned responses - GET/POST /v1/canned/{list,save,delete}.php
Save body: { id (0=new), label, body, classification_filter, channel_filter, sort_order, active }.
Knowledge base - GET/POST /v1/kb/{list,save,delete}.php
Save body: { id (0=new), label, body, tags, active }.
API keys - GET/POST /v1/keys/{list,create,revoke}.php
Session-only (cannot use API key to create another API key). New key is shown once at creation.
Webhooks - GET/POST /v1/webhooks/{list,create,delete}.php
Register a URL to receive classification events. Signing secret is shown once on creation. Verify the X-Gatetrol-Signature header against hash_hmac('sha256', $rawBody, $secret).
Billing - POST /v1/billing/{checkout,portal}.php
Checkout body: { plan: "starter|email_sms|pro|concierge", success_url, cancel_url } → returns Stripe Checkout URL.
Portal body: { return_url } → returns Stripe Customer Portal URL. Customer must have completed Checkout first.
Tenants with billing_mode='external_jobtrol' cannot use these endpoints (their billing is handled by Jobtrol).
Inbound webhooks (configure with your carrier)
- Email: Postmark inbound stream POSTs JSON to
https://gatetrol.com/v1/in/email.php. Tenant resolved fromToaddress:{inbound_token}@in.gatetrol.com. - SMS:
https://gatetrol.com/v1/in/sms.php?carrier=twilio(form-POST) or?carrier=telnyx(JSON). Tenant resolved by registeredTonumber. - Voice (Twilio):
https://gatetrol.com/v1/in/voice.php(greeting + Gather),/voice_gather.php(per turn),/voice_status.php(call status callback),/voice_transcribe.php(voicemail transcription callback). - Stripe:
https://gatetrol.com/v1/in/stripe.php. Verify withSTRIPE_WEBHOOK_SECRET.
Outbound webhook payload format
Gatetrol POSTs JSON to your registered URL(s). Verify X-Gatetrol-Signature (HMAC-SHA256 of the raw body using your signing secret). Headers:
X-Gatetrol-Signature: <hex>X-Gatetrol-Event: classification.urgent(or.created/.needs_review)X-Gatetrol-Delivery: <delivery_id>- idempotency key
Body shape:
{
"event": "classification.urgent",
"tenant_id": 5,
"timestamp": "2026-05-14T17:42:00+00:00",
"data": {
"classification_id": 123,
"tenant": { "id": 5, "email": "..." },
"message": {
"channel": "email",
"sender_address": "...",
"sender_name": "...",
"subject": "...",
"body_preview": "..."
},
"classification": {
"class": "urgent",
"confidence": 0.92,
"reason": "..."
}
}
}
Respond with HTTP 2xx within 8 seconds; Gatetrol retries failed deliveries on a 60s → 5m → 30m → 2h → 12h → 24h schedule, then marks dead.
Magic-link sign-in (dashboard)
- POST
emailtohttps://gatetrol.com/v1/auth/request.php→ mails a sign-in link (30-min TTL). - Clicking the link hits
/v1/auth/verify.php?token=..., which establishes a session and redirects. - Sign out:
/v1/auth/logout.php.
Error format
{ "ok": false, "error": "code_snake_case", "message": "Human-readable detail (optional)" }