{"openapi":"3.1.0","info":{"title":"TextManner API","version":"1.0.0","description":"Business SMS for US numbers. Every response carries X-Request-Id. Sent means the carrier accepted the message; delivered means a positive handset report; unknown and expired mean no conclusive result.","contact":{"name":"TextManner support","email":"support@textmanner.com","url":"https://textmanner.com"}},"servers":[{"url":"http://api.textmanner.com/v1"}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"tm_test_... or tm_live_... keys created in the dashboard. Each key belongs to one workspace and one environment."}},"schemas":{"Message":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["message"]},"environment":{"type":"string","enum":["test","live"]},"direction":{"type":"string","enum":["outbound","inbound"]},"to":{"type":"string"},"from":{"type":"string"},"body":{"type":"string"},"status":{"type":"string","enum":["queued","accepted","sent","delivered","undelivered","failed","unknown","expired","canceled","received"]},"encoding":{"type":"string","enum":["gsm7","ucs2"]},"segments":{"type":"integer","exclusiveMinimum":0},"error_code":{"type":["string","null"]},"error_message":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"scheduled_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","object","environment","direction","to","from","body","status","encoding","segments","error_code","error_message","metadata","scheduled_at","created_at","updated_at"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","enum":["invalid_request","authentication_error","permission_error","not_found","idempotency_error","rate_limited","sending_blocked","internal_error"]},"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"},"param":{"type":"string"}},"required":["type","code","message","request_id"]}},"required":["error"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook_endpoint"]},"environment":{"type":"string","enum":["test","live"]},"url":{"type":"string"},"description":{"type":["string","null"]},"events":{"type":"array","items":{"type":"string","enum":["message.status","message.received","registration.status"]}},"status":{"type":"string","enum":["active","disabled"]},"secret":{"type":"string"},"created_at":{"type":"string"}},"required":["id","object","environment","url","description","events","status","created_at"]},"WebhookEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["message.status","message.received","registration.status"]},"environment":{"type":"string","enum":["test","live"]},"created_at":{"type":"string"},"data":{"type":"object","additionalProperties":{}}},"required":["id","object","type","environment","created_at","data"]},"MessagePage":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]},"WebhookEndpointPage":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]}},"parameters":{}},"paths":{"/messages":{"post":{"summary":"Queue one outbound SMS","description":"Validates the destination, sender, approval state, suppression list and segment count, then queues the message. The response status is queued; delivery updates arrive through webhooks or GET /messages/{id}.","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Required. Unique per workspace, environment, method and path; retained 72 hours."},"required":true,"description":"Required. Unique per workspace, environment, method and path; retained 72 hours.","name":"Idempotency-Key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":2,"maxLength":20},"from":{"type":"string","minLength":2,"maxLength":20},"body":{"type":"string","minLength":1,"maxLength":1600},"metadata":{"type":"object","additionalProperties":{"type":"string","maxLength":500}},"scheduled_at":{"type":"string","format":"date-time"}},"required":["to","body"]}}}},"responses":{"202":{"description":"Queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing scope or sending blocked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"List outbound messages","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":"string","enum":["queued","accepted","sent","delivered","undelivered","failed","unknown","expired","canceled","received"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"to","in":"query"}],"responses":{"200":{"description":"A page of messages, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePage"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/messages/{id}":{"get":{"summary":"Message details and latest status","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string","example":"msg_01a166b7befe722abdb4a0696fd0af69"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inbound-messages":{"get":{"summary":"List received SMS","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"}],"responses":{"200":{"description":"A page of inbound messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePage"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-endpoints":{"get":{"summary":"List webhook endpoints","security":[{"ApiKey":[]}],"responses":{"200":{"description":"Endpoints of the key's environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPage"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a webhook endpoint","description":"The signing secret is returned once. Verify TextManner-Signature (t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<body>\">) on every delivery.","security":[{"ApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":500,"format":"uri"},"description":{"type":"string","maxLength":200},"events":{"type":"array","items":{"type":"string","enum":["message.status","message.received","registration.status"]},"minItems":1}},"required":["url","events"]}}}},"responses":{"201":{"description":"Created, with the secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing scope or sending blocked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-endpoints/{id}/rotate":{"post":{"summary":"Rotate an endpoint's signing secret","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The new secret","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"secret":{"type":"string"}},"required":["id","secret"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook-endpoints/{id}":{"delete":{"summary":"Delete a webhook endpoint","security":[{"ApiKey":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}