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

# Embedded Signup: Redirect Flow

> Integrate WhatsApp account connection using server-side redirects

The redirect flow allows platform developers to embed WhatsApp account connection in their applications using server-side redirects. This is ideal for web applications where you control the backend.

<Info>
  This guide is for platform developers building applications on top of Chirp. If you just want to connect your own WhatsApp Business Account, use the [dashboard method](/whatsapp/embedded-signup).
</Info>

## When to Use This Flow

Choose the redirect flow when:

* You have a server-side application that can handle redirects
* You want a simple, well-understood OAuth-like pattern
* You need to support mobile apps with custom URL schemes
* You prefer server-side token exchange over client-side JavaScript

For a client-side popup experience, see the [Popup Flow](/whatsapp/embedded-signup-popup).

## How It Works

1. **Create Session** - Your server calls the Chirp API to create an embedded signup session
2. **Redirect User** - Redirect your user to the session URL
3. **User Completes Signup** - User authenticates with Meta and grants permissions
4. **Callback** - User is redirected back to your `redirect_uri` with the result

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Your App
    participant Chirp
    participant Meta

    User->>Your App: Click "Connect WhatsApp"
    Your App->>Chirp: POST /v1/organization/embedded-signup/sessions
    Chirp-->>Your App: { url, id, expires_at }
    Your App->>User: Redirect to Chirp URL
    User->>Chirp: Load embed page
    Chirp->>Meta: FB.login()
    User->>Meta: Authenticate & authorize
    Meta->>Chirp: Authorization code
    Chirp->>Chirp: Exchange code, create profile
    Chirp->>Your App: Redirect to redirect_uri?status=success&state=...
    Your App->>User: Show success
```

## Creating a Session

Use your Admin Key to create an embedded signup session:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions \
    -H "Authorization: Bearer YOUR_ADMIN_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "redirect_uri": "https://yourapp.com/whatsapp/callback",
      "state": "your-csrf-token-123"
    }'
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  const session = await chirp.admin.embeddedSignup.createSession({
    redirect_uri: "https://yourapp.com/whatsapp/callback",
    state: "your-csrf-token-123"
  });

  // session.id, session.url, session.expiresAt
  ```
</CodeGroup>

**Response:**

```json icon="code" title="Session Response" theme={null}
{
  "id": "wss_abc123...",
  "url": "https://dashboard.chirp.com/embed/connect?token=...",
  "expires_at": "2024-01-15T12:15:00.000Z"
}
```

### Parameters

| Parameter      | Required | Description                                                                                                               |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| `redirect_uri` | Yes      | URL to redirect after completion. Supports HTTPS URLs and mobile app schemas (e.g., `myapp://callback`)                   |
| `state`        | Yes      | CSRF token (max 512 chars). Returned unchanged in the callback                                                            |
| `metadata`     | No       | JSON object (max 10KB) for storing your internal identifiers (e.g., `externalUserId`, `businessName`)                     |
| `prefill`      | No       | Pre-fill configuration to auto-populate the Meta signup form. See [Pre-fill Configuration](#pre-fill-configuration) below |

## Pre-fill Configuration

You can pre-populate the Meta Embedded Signup form with business information to improve conversion rates. This is especially useful when you already have your user's business details.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions \
    -H "Authorization: Bearer YOUR_ADMIN_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "redirect_uri": "https://yourapp.com/whatsapp/callback",
      "state": "your-csrf-token-123",
      "prefill": {
        "business": {
          "name": "Acme Corporation",
          "email": "contact@acme.com",
          "website": "https://acme.com",
          "phone": {
            "code": 1,
            "number": "5551234567"
          },
          "address": {
            "streetAddress1": "123 Main St",
            "city": "San Francisco",
            "state": "CA",
            "zipPostal": "94105",
            "country": "US"
          },
          "timezone": "America/Los_Angeles"
        },
        "phone": {
          "displayName": "Acme Support",
          "category": "ENTERTAIN",
          "description": "Customer support for Acme products"
        }
      }
    }'
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  const session = await chirp.admin.embeddedSignup.createSession({
    redirect_uri: "https://yourapp.com/whatsapp/callback",
    state: "your-csrf-token-123",
    prefill: {
      business: {
        name: "Acme Corporation",
        email: "contact@acme.com",
        website: "https://acme.com",
        phone: {
          code: 1,
          number: "5551234567"
        },
        address: {
          streetAddress1: "123 Main St",
          city: "San Francisco",
          state: "CA",
          zipPostal: "94105",
          country: "US"
        },
        timezone: "America/Los_Angeles"
      },
      phone: {
        displayName: "Acme Support",
        category: "ENTERTAIN",
        description: "Customer support for Acme products"
      }
    }
  });
  ```
</CodeGroup>

### Pre-fill Fields

| Field                   | Description                                                                                       |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| `business.name`         | Business name (max 255 chars)                                                                     |
| `business.email`        | Business email address                                                                            |
| `business.website`      | Business website URL                                                                              |
| `business.phone.code`   | Country calling code (e.g., `1` for US)                                                           |
| `business.phone.number` | Phone number without country code                                                                 |
| `business.address`      | Business address with `streetAddress1`, `streetAddress2`, `city`, `state`, `zipPostal`, `country` |
| `business.timezone`     | IANA timezone (e.g., `"America/Los_Angeles"`)                                                     |
| `phone.displayName`     | WhatsApp Business display name (max 512 chars)                                                    |
| `phone.category`        | Business category                                                                                 |
| `phone.description`     | Business description (max 512 chars)                                                              |

<Info>
  The `country` field uses ISO 3166-1 alpha-2 codes (e.g., `"US"`, `"GB"`, `"DE"`). The pre-fill data is limited to 10KB total.
</Info>

## Handling the Callback

After the user completes (or cancels) the signup, they're redirected to your `redirect_uri` with query parameters:

**Success:**

```
https://yourapp.com/whatsapp/callback?status=success&state=your-csrf-token-123
```

**Error:**

```
https://yourapp.com/whatsapp/callback?status=error&state=your-csrf-token-123&error=waba_already_connected
```

### Error Codes

| Error Code               | Description                                                             |
| ------------------------ | ----------------------------------------------------------------------- |
| `session_expired`        | The session URL expired (15 minute TTL)                                 |
| `waba_already_connected` | The WhatsApp Business Account is already connected to this organization |
| `meta_api_error`         | Error from Meta's API during token exchange                             |
| `code_expired`           | The authorization code from Meta expired (30 second TTL)                |
| `signup_failed`          | General signup failure                                                  |

## Completing an Interrupted Session

If a user completes the Meta signup but the redirect fails (network error, browser closed, etc.), you can complete the session manually using the WABA ID:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions/{sessionId}/complete \
    -H "Authorization: Bearer YOUR_ADMIN_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "wabaId": "123456789"
    }'
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  const result = await chirp.admin.embeddedSignup.completeSession(
    "wss_abc123...",
    { wabaId: "123456789" }
  );
  ```
</CodeGroup>

This is useful when you receive a `PARTNER_APP_INSTALLED` webhook indicating the user completed signup on Meta's side but didn't return to your application.

## Security Considerations

<Warning>
  Always validate the `state` parameter in your callback to prevent CSRF attacks. Compare it to the value you originally sent when creating the session.
</Warning>

* **Session Expiration** - Sessions expire after 15 minutes
* **One-Time Use** - Each session can only be completed once
* **HTTPS Required** - Use HTTPS for your `redirect_uri` in production
* **State Validation** - Always verify the `state` parameter matches what you sent

## Mobile App Integration

For mobile apps, use a custom URL scheme as your `redirect_uri`:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions \
    -H "Authorization: Bearer YOUR_ADMIN_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "redirect_uri": "myapp://whatsapp/callback",
      "state": "mobile-csrf-token"
    }'
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  const session = await chirp.admin.embeddedSignup.createSession({
    redirect_uri: "myapp://whatsapp/callback",
    state: "mobile-csrf-token"
  });

  // Open session.url in a webview or browser
  ```
</CodeGroup>

Then handle the callback in your app's URL handler.

## Managing Sessions

### List Sessions

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions \
    -H "Authorization: Bearer YOUR_ADMIN_KEY"
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  const sessions = await chirp.admin.embeddedSignup.listSessions();

  // With filters
  const pendingSessions = await chirp.admin.embeddedSignup.listSessions({
    status: "pending",
    limit: 50
  });
  ```
</CodeGroup>

### Get Session Status

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions/{sessionId} \
    -H "Authorization: Bearer YOUR_ADMIN_KEY"
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  const session = await chirp.admin.embeddedSignup.getSession("wss_abc123...");
  ```
</CodeGroup>

### Delete Session

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.buildwithchirp.com/v1/organization/embedded-signup/sessions/{sessionId} \
    -H "Authorization: Bearer YOUR_ADMIN_KEY"
  ```

  ```typescript SDK theme={null}
  import ChirpSDK from "@buildwithchirp/sdk";

  const chirp = new ChirpSDK({ apiKey: "YOUR_ADMIN_KEY" });

  await chirp.admin.embeddedSignup.cancelSession("wss_abc123...");
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api_reference/introduction">
    Full API documentation for embedded signup sessions
  </Card>

  <Card title="Popup Flow" icon="window-restore" href="/whatsapp/embedded-signup-popup">
    Alternative client-side popup integration
  </Card>
</CardGroup>
