AgentMessage
Demo

Start a textdemo conversation

POST
/v1/demo/start

Starts a textdemo conversation: records implied-by-submit consent for the platform-owned demo organization and fires the agent's opening SMS to contact_number, both inside a single transaction so the consent audit row and the queued greeting commit together or not at all.

This endpoint is called server-to-server by the AgentMessage marketing-site proxy, never by a browser directly. The proxy fills the evidence_* and page_url fields from the inbound browser request; the demo organization and demo sending number are server-side configuration and are never accepted from the request body.

contact_number is normalized to E.164 before validation, so a national-format US number submitted by the form still resolves. The agreement_text blob is the exact opt-in language the user agreed to; its SHA-256 is stored on the consent-history row as tamper-evident evidence (the raw text is not persisted).

On a brand-new contact the conversation is opened, the canned greeting is enqueued, and the call returns 202 Accepted with conversation_started: true and the queued greeting's outbound_message_id. On a contact that already has demo history the call is an idempotent no-op (no second greeting) and returns 200 OK with conversation_started: false.

Requires the demo:write scope. The route is served only when the textdemo live-SMS path is enabled (OPENAI_API_KEY + AM_TEXTDEMO_DEMO_ORG_ID + AM_TEXTDEMO_DEMO_NUMBER all set); otherwise it is unmounted. Full flow: docs/textdemo.md.

AuthorizationBearer <token>

Authenticate by sending your API key as a bearer token: Authorization: Bearer am_live_.... Every request is automatically scoped to the organization that owns the key and to the scopes granted to that key.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/demo/start" \  -H "Content-Type: application/json" \  -d '{    "contact_number": "+15554443333",    "name": "Jamie Rivera",    "agreement_text": "I agree to receive a text-message demo from AgentMessage. Msg & data rates may apply. Reply STOP to opt out.",    "captured_at": "2026-06-03T15:23:01Z",    "evidence_ip": "203.0.113.42",    "evidence_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",    "page_url": "https://agentmessage.io/demo"  }'
{
  "success": true,
  "data": {
    "consent_id": "0190a1b2-c3d4-e5f6-a7b8-c9d0e1f2a3b4",
    "conversation_started": false,
    "message": "conversation already active"
  }
}
{
  "success": true,
  "data": {
    "consent_id": "0190a1b2-c3d4-e5f6-a7b8-c9d0e1f2a3b4",
    "conversation_started": true,
    "message": "greeting enqueued",
    "outbound_message_id": "8f3a2b1c-1c2d-4e5f-9a8b-0c1d2e3f4a5b"
  }
}
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "authentication failed",
    "request_id": "01JTBQH2FZ8K1RXC0WJ4Z9P3VM"
  }
}
{
  "success": false,
  "error": {
    "code": "FORBIDDEN",
    "message": "missing required scope",
    "request_id": "01JTBQH2FZ8K1RXC0WJ4Z9P3VM"
  }
}
{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "validation failed",
    "request_id": "01JTBQH2FZ8K1RXC0WJ4Z9P3VM",
    "details": {
      "to": "must be E.164",
      "body": "must be 1..1600 chars"
    }
  }
}