> ## Documentation Index
> Fetch the complete documentation index at: https://archie.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Twilio

> Send SMS, place voice calls, and run verification flows from your Archie app through Twilio's programmable communications API.

The Twilio integration handles SMS, voice, and verification in your Archie app. Once connected, you can send messages, kick off verification codes, and receive inbound events — all through the auto-generated GraphQL API.

<Note>
  A typed TypeScript SDK for integrations is coming with the next archie-app release. This page documents the GraphQL operation surface available today.
</Note>

## Enable the integration

Open **Integrations** in the left sidebar and pick Twilio.

You'll need from your [Twilio Console](https://console.twilio.com/):

* **Account SID** — starts with `AC...`. Acts as the username for API calls.
* **Auth Token** — your account's secret. Treat it like a password.

Optional, depending on what you're building:

* **Messaging Service SID** — `MG...`, if you use a Messaging Service for SMS.
* **Verify Service SID** — `VA...`, if you use Twilio Verify for OTP and 2FA flows.

The auth token is encrypted with AES-256-GCM at rest and only decrypted in the backend at request time.

## What you can do

* **SMS** — send single and bulk messages, with Messaging Service support
* **Voice** — place calls, send TwiML responses, manage call status
* **Verify** — start verification challenges, check codes, run 2FA flows
* **Webhook events** — receive inbound SMS, status callbacks, and Verify events

## Sending an SMS

```graphql theme={null}
mutation {
  twilio_sendSms(input: {
    to: "+15551234567"
    from: "+15557654321"
    body: "Your code is 123456"
  }) {
    sid
    status
  }
}
```

For high-volume SMS, send through a Messaging Service instead of a single from-number — it handles rotation, carrier registration, and opt-out:

```graphql theme={null}
mutation {
  twilio_sendSms(input: {
    to: "+15551234567"
    messagingServiceSid: "MG..."
    body: "Welcome to Yourapp"
  }) {
    sid
    status
  }
}
```

## Verification flows (Twilio Verify)

Start a verification:

```graphql theme={null}
mutation {
  twilio_startVerification(input: {
    serviceSid: "VA..."
    to: "+15551234567"
    channel: "sms"
  }) {
    sid
    status
  }
}
```

Check a code:

```graphql theme={null}
mutation {
  twilio_checkVerification(input: {
    serviceSid: "VA..."
    to: "+15551234567"
    code: "123456"
  }) {
    valid
    status
  }
}
```

Verify supports SMS, voice, email, and TOTP channels — pick the one that matches your flow.

## Placing a voice call

```graphql theme={null}
mutation {
  twilio_makeCall(input: {
    to: "+15551234567"
    from: "+15557654321"
    twimlUrl: "https://yourapp.com/voice/welcome"
  }) {
    sid
    status
  }
}
```

`twimlUrl` should return TwiML that tells Twilio what to say or play.

## Webhooks

Configure inbound webhooks in the Twilio Console:

* **Phone Numbers → Active numbers → \[number] → Messaging** — point at Archie's generated SMS webhook URL for inbound messages.
* **Phone Numbers → Active numbers → \[number] → Voice** — point at Archie's generated voice webhook URL.
* **Verify Service → Webhooks** — point at Archie's Verify webhook URL for status changes.

Archie verifies Twilio's `X-Twilio-Signature` header before accepting events. See [Webhooks](/features/backend/integrations/webhooks) for handling them in custom functions.

## FAQ

<AccordionGroup>
  <Accordion title="Do I need a Messaging Service or can I just use a single from-number?">
    A single from-number works fine for low volume and dev testing. Use a Messaging Service when you start sending more than a few hundred SMS per day, want number rotation across multiple numbers, or need carrier-mandated registration (A2P 10DLC in the US).
  </Accordion>

  <Accordion title="What's the difference between sending an OTP via SMS directly and using Twilio Verify?">
    Verify handles code generation, expiry, attempt limits, and channel fallback (SMS, voice, email, TOTP) for you. If you send OTPs via raw SMS, you implement all of that yourself. Use Verify unless you have a reason not to.
  </Accordion>

  <Accordion title="How do I receive inbound SMS replies?">
    Set the messaging webhook on your Twilio number to Archie's generated SMS webhook URL. Inbound messages arrive as webhook events you can react to in a custom function — see [Webhooks](/features/backend/integrations/webhooks).
  </Accordion>

  <Accordion title="Can I send international SMS?">
    Yes, but you need to enable geo permissions in the Twilio Console (**Messaging → Settings → Geo Permissions**) and may need country-specific sender registration. Twilio also charges per-country rates.
  </Accordion>

  <Accordion title="What happens to my flow if Twilio is down?">
    Your call to `twilio_sendSms` returns an error and your code can decide what to do — retry, fall back to email through SendGrid, or queue for later. Webhook events are retried by Twilio with backoff if your endpoint isn't reachable.
  </Accordion>
</AccordionGroup>
