{"openapi":"3.0.3","info":{"title":"Bullion Messaging API","version":"0.2.0","description":"Carrier-grade SMS · WhatsApp · Voice. Authenticate with a Bearer API key (or portal JWT). Set the `X-Sandbox: 1` header to simulate sends without cost."},"servers":[{"url":"https://srv1721841.hstgr.cloud:8433","description":"Live"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key (bm_live_… / bm_test_…) or portal JWT."}},"schemas":{"Message":{"type":"object","properties":{"id":{"type":"string"},"channel":{"type":"string","enum":["sms","whatsapp","voice"]},"to":{"type":"string"},"from":{"type":"string","nullable":true},"body":{"type":"string","nullable":true},"segments":{"type":"integer"},"cost":{"type":"number"},"status":{"type":"string","enum":["accepted","sent","delivered","failed","received"]},"created_at":{"type":"string","format":"date-time"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}},"security":[{"bearerAuth":[]}],"paths":{"/v1/auth/login":{"post":{"summary":"Log in","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}},"required":[]}}}},"responses":{"200":{"description":"Tokens + user","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/messages":{"post":{"summary":"Send a message","description":"Priced, wallet-debited and routed to the SMSC. `Idempotency-Key` header makes retries safe; `X-Sandbox: 1` simulates. `fallback` lists channels to auto-retry, in order, if delivery to the primary channel fails — only the channel that delivers is billed.","parameters":[{"in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}},{"in":"header","name":"X-Sandbox","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string"},"channel":{"type":"string","enum":["sms","whatsapp","voice"]},"from":{"type":"string"},"body":{"type":"string"},"template":{"type":"object","description":"WhatsApp template (name, language, components) to open a conversation outside the 24h window.","properties":{"name":{"type":"string"},"language":{"type":"string"},"components":{"type":"array","items":{"type":"object"}}}},"fallback":{"type":"array","items":{"type":"string","enum":["sms","whatsapp","voice"]},"description":"Ordered fallback channels tried on dispatch failure."}},"required":["to","channel"]}}}},"responses":{"201":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/Message"},"balance":{"type":"number","nullable":true}}}}}},"402":{"description":"Insufficient funds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Carrier rejected (refunded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"Search messages","parameters":[{"in":"query","name":"status","required":false,"schema":{"type":"string"}},{"in":"query","name":"channel","required":false,"schema":{"type":"string"}},{"in":"query","name":"to","required":false,"schema":{"type":"string"}},{"in":"query","name":"q","required":false,"schema":{"type":"string"}},{"in":"query","name":"since","required":false,"schema":{"type":"string"}},{"in":"query","name":"until","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Messages","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}}}}}}}}},"/v1/messages/{id}":{"get":{"summary":"Trace a message","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Full trace","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/messages/batch":{"post":{"summary":"Send a batch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object"}}},"required":["messages"]}}}},"responses":{"201":{"description":"All accepted","content":{"application/json":{"schema":{"type":"object"}}}},"207":{"description":"Partial","content":{"application/json":{"schema":{"type":"object"}}}},"422":{"description":"None accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/campaigns":{"post":{"summary":"Create a campaign","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"channel":{"type":"string"},"body":{"type":"string"},"recipients":{"type":"array","items":{"type":"string"}},"list_id":{"type":"string"},"template_id":{"type":"string"},"scheduled_at":{"type":"string"}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object"}}}}}},"get":{"summary":"List campaigns","responses":{"200":{"description":"Campaigns","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/campaigns/{id}/launch":{"post":{"summary":"Launch a campaign","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Launched","content":{"application/json":{"schema":{"type":"object"}}}},"409":{"description":"Not launchable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/voice/calls":{"post":{"summary":"Place a call","description":"LCR + conversion routed with failover. `say` speaks TTS; `record` records.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string"},"from":{"type":"string"},"say":{"type":"string"},"record":{"type":"boolean"}},"required":["to"]}}}},"responses":{"201":{"description":"Call placed","content":{"application/json":{"schema":{"type":"object"}}}},"503":{"description":"Voice not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/voice/numbers/search":{"get":{"summary":"Search DIDs to buy","parameters":[{"in":"query","name":"country","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Available numbers","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/balance":{"get":{"summary":"Wallet balance","responses":{"200":{"description":"Balance","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/webhook-subscriptions":{"post":{"summary":"Subscribe to events (HMAC-signed)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}}},"required":["url"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}