# Connect WhatsApp numbers (/docs/api-reference/whatsapp/importWhatsappNumbers)

> Connects numbers from your own WhatsApp Business Account with your Meta access token. List them first with [Preview numbers](/docs/api-reference/whatsapp/previewWhatsappNumbers), then pass the ids you want.

> **Set up WhatsApp first.** Connect a WhatsApp number in the dashboard or with [Connect numbers](/docs/api-reference/whatsapp/importWhatsappNumbers). Included on every paid plan. [See plans](https://omnidim.io/pricing).

**POST** `/whatsapp/numbers`

Connects numbers from your own WhatsApp Business Account with your Meta
access token. List them first with
[Preview numbers](/docs/api-reference/whatsapp/previewWhatsappNumbers),
then pass the ids you want.

The token must never expire and must carry both WhatsApp permissions
(`whatsapp_business_management` and `whatsapp_business_messaging`). A
system user token does. Add `app_secret` to receive replies. Without
it the number can send but not receive.

Connecting a number again updates it: send a new `access_token` or
`app_secret` the same way to change either. One number failing does
not stop the others. It is listed in `failed` with the reason.

```yaml
operationId: importWhatsappNumbers
requestBody:
  required: true
  content:
    application/json:
      schema:
        type: object
        required:
          - waba_id
          - access_token
          - phone_number_ids
        properties:
          waba_id:
            type: string
            description: Your WhatsApp Business Account id, from WhatsApp Manager.
          access_token:
            type: string
            description: >-
              A Meta access token that never expires, with both WhatsApp permissions. Stored, never
              returned.
          phone_number_ids:
            type: array
            minItems: 1
            items:
              type: string
            description: Meta's ids for the numbers to connect, as Preview numbers lists them.
          app_secret:
            type: string
            description: Your Meta app's secret. Turns on replies. Stored, never returned.
      example:
        waba_id: '102938475610293'
        access_token: EAAG...
        phone_number_ids:
          - '106540352242922'
        app_secret: 3f9c...
responses:
  '200':
    description: The connected numbers, and any that failed.
    content:
      application/json:
        schema:
          type: object
          properties:
            data:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: integer
                    example: 412
                  phone_number:
                    type: string
                    example: '+15551234567'
                  provider:
                    type: string
                    enum:
                      - meta
                      - twilio
                      - sensibot
                      - interakt
                    description: Who carries the number. `meta` is the WhatsApp Cloud API.
                  name:
                    type: string
                    nullable: true
                    description: The label you gave the number.
                  status:
                    type: string
                    enum:
                      - active
                      - restricted
                      - disconnected
                    description: |
                      `active` can send. `restricted` is limited by WhatsApp.
                      `disconnected` is missing its credentials, so it cannot send.
                  account_restriction:
                    type: string
                    nullable: true
                    description: WhatsApp's own restriction on the account, when there is one.
                  agent_id:
                    type: integer
                    nullable: true
                    description: The agent that answers this number, when one is attached.
                  quality_rating:
                    type: string
                    nullable: true
                    description: WhatsApp's quality rating. Meta numbers only.
                  messaging_limit:
                    type: string
                    nullable: true
                    description: How many customers you can start chats with in 24 hours. Meta numbers only.
                  capabilities:
                    type: object
                    description: What this number can send, and how its delivery status is learned.
                    properties:
                      types:
                        type: array
                        description: The message types this number can send. Always includes `text`.
                        items:
                          type: string
                          enum:
                            - text
                            - template
                            - image
                            - document
                      reply_to:
                        type: boolean
                        description: Supports quoted replies, read receipts, typing and reactions.
                      window_enforced:
                        type: boolean
                        description: >-
                          Free-form sends are refused outside the 24-hour window. True on WhatsApp
                          Cloud numbers.
                      delivery_status:
                        type: string
                        enum:
                          - push
                          - polled
                          - none
                        description: >-
                          How sent status is learned. `push` is a webhook, `polled` is a periodic
                          read, `none` is not at all.
                      template_sync:
                        type: boolean
                        description: Templates can be pulled from the provider with `syncWhatsappTemplates`.
                  receiving:
                    type: boolean
                    description: >-
                      This request turned replies on. It is `false` when you did not send
                      `app_secret`, even if replies were already on for the number.
                  receiving_error:
                    type: string
                    nullable: true
                    description: Why replies could not be turned on, when they could not.
            failed:
              type: array
              items:
                type: object
                properties:
                  phone_number_id:
                    type: string
                  message:
                    type: string
                    example: >-
                      This WhatsApp number is already connected to another account. Disconnect it
                      there first, then import it again. Contact support if you cannot access that
                      account.
  '400':
    description: |
      `missing_fields` (`waba_id` or `access_token`), `invalid_json` (the
      body is not a JSON object), `invalid_parameter` (`phone_number_ids`),
      `token_invalid`, `token_expires`, `token_missing_permissions`,
      `invalid_request` (the account has no numbers, or Meta did not say which
      app the token belongs to), or `import_failed` (no number connected;
      `failed` says why for each).
    content:
      application/json:
        schema:
          type: object
          description: |
            The error envelope for every WhatsApp route. Some errors add keys:
            `fields` (the template parameters a send still needs), `ref` (a
            500's support reference) and `failed` (on `import_failed`).
          properties:
            error:
              type: string
              description: Machine-readable category, such as `invalid_request`.
            error_description:
              type: string
              description: Human-readable explanation.
            code:
              type: string
              description: Stable, specific reason, such as `window_closed`.
            request_id:
              type: string
              description: >-
                Correlates this response with the server log. Also sent as the `X-Request-Id`
                header.
            fields:
              type: array
              items:
                type: string
              description: >-
                On a template send missing parameters (`missing_fields`), the field keys you still
                need.
            ref:
              type: string
              description: On a `500`, the reference to quote to support.
            failed:
              type: array
              items:
                type: object
                properties:
                  phone_number_id:
                    type: string
                  message:
                    type: string
                    example: >-
                      This WhatsApp number is already connected to another account. Disconnect it
                      there first, then import it again. Contact support if you cannot access that
                      account.
              description: On `import_failed`, each number and why it could not be connected.
        example:
          error: invalid_request
          error_description: This token expires on 27 Nov. Generate a new one set to never expire.
          code: token_expires
          request_id: req_5b8e2d1c7a94
  '401':
    description: Missing or invalid API key.
    content:
      application/json:
        schema:
          type: object
          description: |
            The error envelope for every WhatsApp route. Some errors add keys:
            `fields` (the template parameters a send still needs), `ref` (a
            500's support reference) and `failed` (on `import_failed`).
          properties:
            error:
              type: string
              description: Machine-readable category, such as `invalid_request`.
            error_description:
              type: string
              description: Human-readable explanation.
            code:
              type: string
              description: Stable, specific reason, such as `window_closed`.
            request_id:
              type: string
              description: >-
                Correlates this response with the server log. Also sent as the `X-Request-Id`
                header.
            fields:
              type: array
              items:
                type: string
              description: >-
                On a template send missing parameters (`missing_fields`), the field keys you still
                need.
            ref:
              type: string
              description: On a `500`, the reference to quote to support.
            failed:
              type: array
              items:
                type: object
                properties:
                  phone_number_id:
                    type: string
                  message:
                    type: string
                    example: >-
                      This WhatsApp number is already connected to another account. Disconnect it
                      there first, then import it again. Contact support if you cannot access that
                      account.
              description: On `import_failed`, each number and why it could not be connected.
        example:
          error: unauthorized
          error_description: Missing or invalid API key
          code: invalid_api_key
          request_id: req_6e2b9d4f1a38
  '403':
    description: |
      `feature_not_enabled` when your plan or role cannot use WhatsApp,
      `permission_denied` when the key's user cannot make changes, or
      `service_unavailable` when the account is on hold.
    content:
      application/json:
        schema:
          type: object
          description: |
            The error envelope for every WhatsApp route. Some errors add keys:
            `fields` (the template parameters a send still needs), `ref` (a
            500's support reference) and `failed` (on `import_failed`).
          properties:
            error:
              type: string
              description: Machine-readable category, such as `invalid_request`.
            error_description:
              type: string
              description: Human-readable explanation.
            code:
              type: string
              description: Stable, specific reason, such as `window_closed`.
            request_id:
              type: string
              description: >-
                Correlates this response with the server log. Also sent as the `X-Request-Id`
                header.
            fields:
              type: array
              items:
                type: string
              description: >-
                On a template send missing parameters (`missing_fields`), the field keys you still
                need.
            ref:
              type: string
              description: On a `500`, the reference to quote to support.
            failed:
              type: array
              items:
                type: object
                properties:
                  phone_number_id:
                    type: string
                  message:
                    type: string
                    example: >-
                      This WhatsApp number is already connected to another account. Disconnect it
                      there first, then import it again. Contact support if you cannot access that
                      account.
              description: On `import_failed`, each number and why it could not be connected.
        example:
          error: forbidden
          error_description: You do not have permission to make changes to WhatsApp.
          code: permission_denied
          request_id: req_9f2c1a4b7d3e
  '500':
    description: Something went wrong on our side. Quote `ref` to support.
    content:
      application/json:
        schema:
          type: object
          description: |
            The error envelope for every WhatsApp route. Some errors add keys:
            `fields` (the template parameters a send still needs), `ref` (a
            500's support reference) and `failed` (on `import_failed`).
          properties:
            error:
              type: string
              description: Machine-readable category, such as `invalid_request`.
            error_description:
              type: string
              description: Human-readable explanation.
            code:
              type: string
              description: Stable, specific reason, such as `window_closed`.
            request_id:
              type: string
              description: >-
                Correlates this response with the server log. Also sent as the `X-Request-Id`
                header.
            fields:
              type: array
              items:
                type: string
              description: >-
                On a template send missing parameters (`missing_fields`), the field keys you still
                need.
            ref:
              type: string
              description: On a `500`, the reference to quote to support.
            failed:
              type: array
              items:
                type: object
                properties:
                  phone_number_id:
                    type: string
                  message:
                    type: string
                    example: >-
                      This WhatsApp number is already connected to another account. Disconnect it
                      there first, then import it again. Contact support if you cannot access that
                      account.
              description: On `import_failed`, each number and why it could not be connected.
        example:
          error: server_error
          error_description: >-
            Something went wrong on our side. Please try again shortly, or contact support with
            reference 9a1f3e8b02c4.
          ref: 9a1f3e8b02c4
          code: server_error
          request_id: req_9a1f3e8b02c4
  '502':
    description: '`upstream_error`: Meta could not be reached or refused the request. Nothing was connected.'
    content:
      application/json:
        schema:
          type: object
          description: |
            The error envelope for every WhatsApp route. Some errors add keys:
            `fields` (the template parameters a send still needs), `ref` (a
            500's support reference) and `failed` (on `import_failed`).
          properties:
            error:
              type: string
              description: Machine-readable category, such as `invalid_request`.
            error_description:
              type: string
              description: Human-readable explanation.
            code:
              type: string
              description: Stable, specific reason, such as `window_closed`.
            request_id:
              type: string
              description: >-
                Correlates this response with the server log. Also sent as the `X-Request-Id`
                header.
            fields:
              type: array
              items:
                type: string
              description: >-
                On a template send missing parameters (`missing_fields`), the field keys you still
                need.
            ref:
              type: string
              description: On a `500`, the reference to quote to support.
            failed:
              type: array
              items:
                type: object
                properties:
                  phone_number_id:
                    type: string
                  message:
                    type: string
                    example: >-
                      This WhatsApp number is already connected to another account. Disconnect it
                      there first, then import it again. Contact support if you cannot access that
                      account.
              description: On `import_failed`, each number and why it could not be connected.
        example:
          error: server_error
          error_description: Couldn't reach Meta to check this token. Please try again shortly.
          code: upstream_error
          request_id: req_2f7a9c4e1b63
```

**curl**

```bash
curl -X POST "https://backend.omnidim.io/api/v1/whatsapp/numbers" \
  -H "Authorization: Bearer $OMNIDIM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "waba_id": "102938475610293",
  "access_token": "EAAG...",
  "phone_number_ids": [
    "106540352242922"
  ],
  "app_secret": "3f9c..."
}'
```