{
  "info": {
    "name": "SAEI API v1",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "description": "Generated from the OpenAPI description. Set the `apiKey` variable to a test key (sk_test_…) to start."
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{apiKey}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.saei.automize.sa/v1"
    },
    {
      "key": "apiKey",
      "value": "sk_test_replace_me"
    }
  ],
  "item": [
    {
      "name": "Account",
      "item": [
        {
          "name": "Check your API key",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/me",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "me"
              ]
            },
            "description": "Returns the workspace, the key's mode and scopes, and your rate limit. The quickest way to confirm a key works."
          }
        }
      ]
    },
    {
      "name": "Messages",
      "item": [
        {
          "name": "List messages sent through the API",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "messages"
              ]
            },
            "description": "Newest first. Live keys list messages sent with the API; test keys list test-mode messages (sent and simulated inbound)."
          }
        },
        {
          "name": "Send a message",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "messages"
              ]
            },
            "description": "One endpoint for every kind of message: set `type` and put the content under a key of the same name: `text`, `template`, `image`, `video`, `audio`, `document`, `sticker`, `location`, `contacts`, `interactive` (reply buttons, lists, link buttons, location requests) or `reaction`.\n\n- **Inside 24 hours** of the customer's last message you can send any type.\n- **Outside that window** (or to start a conversation) only an approved `template` is delivered. Anything else returns `window_closed`.\n- **Instagram and Messenger** (`channel`) take replies only: text and media, inside the 24 hours.\n\nThe response comes back as soon as the channel accepts the message (`status: accepted`). Delivery and read updates arrive as `message.*` webhook events. With a test key, the message is simulated and never reaches WhatsApp.\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to\": \"+966501234567\",\n  \"type\": \"text\",\n  \"text\": {\n    \"body\": \"أهلًا سارة! طلبك جاهز للاستلام 🎉\"\n  },\n  \"reference\": \"order-10482\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Get a message",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/messages/msg_48213",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "messages",
                "msg_48213"
              ]
            },
            "description": "A message and its current status. Works for messages you sent (`msg_…`) and customer messages from webhook events (`imsg_…`)."
          }
        },
        {
          "name": "Mark a customer message as read",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/messages/msg_48213/read",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "messages",
                "msg_48213",
                "read"
              ]
            },
            "description": "Shows the customer blue ticks on their message (and on everything they sent before it). Add `typing_indicator: true` to also show \"typing…\" while you prepare the answer: it lasts up to 25 seconds, or until you reply.\n\nWorks on WhatsApp messages you received (`imsg_…`, from `message.received` events).\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"typing_indicator\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Numbers",
      "item": [
        {
          "name": "List your WhatsApp numbers",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/numbers",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "numbers"
              ]
            },
            "description": "The numbers this workspace sends from, with their quality rating, daily limit and whether they can send right now. Use an `id` as `from` when sending."
          }
        },
        {
          "name": "Get a number",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/numbers/num_3",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "numbers",
                "num_3"
              ]
            },
            "description": "One number and its health. When `can_send` is `false`, `cannot_send_reason` says why (disconnected, token needs reconnecting…); fix it in Settings → WhatsApp."
          }
        }
      ]
    },
    {
      "name": "Templates",
      "item": [
        {
          "name": "List templates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/templates",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "templates"
              ]
            },
            "description": "Your WhatsApp message templates. Each one says what it needs filled in (`variables`) and carries a `send_example` you can paste into `POST /v1/messages`."
          }
        },
        {
          "name": "Create a template",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/templates",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "templates"
              ]
            },
            "description": "Submits a new template to WhatsApp for approval. It comes back `pending`; WhatsApp usually decides within minutes (sometimes up to 24 hours), and you get `template.status_changed` when it does.\n\n`components` are WhatsApp's own: `HEADER`, `BODY` (required), `FOOTER`, `BUTTONS`. Every `{{n}}` placeholder needs an `example` value, or WhatsApp rejects the template. The builder's own checks run first (lengths, button counts, the language list, name unique per WhatsApp account), so most mistakes come back at once as `parameter_invalid`.\n\nFor an image, video or document header, upload the file with `POST /v1/media` and put its `med_…` id in `example.header_handle`: we hand it to WhatsApp for you, and the template then sends with that file by default.\n\nAuthentication (OTP) templates take `otp` instead of `components`, need a plan with OTP verification, and a business verified by Meta.\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"order_shipped\",\n  \"language\": \"ar\",\n  \"category\": \"utility\",\n  \"components\": [\n    {\n      \"type\": \"BODY\",\n      \"text\": \"مرحبًا {{1}}، شُحن طلبك رقم {{2}} وسيصلك خلال يومين.\",\n      \"example\": {\n        \"body_text\": [\n          [\n            \"سارة\",\n            \"10482\"\n          ]\n        ]\n      }\n    },\n    {\n      \"type\": \"BUTTONS\",\n      \"buttons\": [\n        {\n          \"type\": \"URL\",\n          \"text\": \"تتبّع الشحنة\",\n          \"url\": \"https://shop.example.com/track/{{1}}\",\n          \"example\": [\n            \"https://shop.example.com/track/10482\"\n          ]\n        }\n      ]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Get a template",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/templates/tpl_27",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "templates",
                "tpl_27"
              ]
            },
            "description": "One template, its components as WhatsApp approved them, and for a rejected template WhatsApp's reason when it gave one."
          }
        },
        {
          "name": "Delete a template",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/templates/tpl_27",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "templates",
                "tpl_27"
              ]
            },
            "description": "Deletes the template here and at WhatsApp. Refused with `resource_in_use` while a scheduled or running campaign uses it. WhatsApp does not let the same name be reused for 30 days."
          }
        }
      ]
    },
    {
      "name": "Media",
      "item": [
        {
          "name": "List files",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/media",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "media"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Upload a file",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/media",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "media"
              ]
            },
            "description": "Adds a file to the workspace media library and gives it a permanent public URL. Send its `id` as the `media_id` of an `image`, `video`, `audio`, `document` or `sticker` message, as often as you like.\n\nSend the file as `multipart/form-data` with the `type` it will be sent as. WhatsApp's limits are checked here, before anything is sent: images JPEG/PNG up to 5 MB, video MP4/3GPP up to 16 MB, audio up to 16 MB, documents up to 100 MB, stickers WebP up to 100 KB (500 KB animated).\n",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": []
                },
                {
                  "key": "type",
                  "type": "text",
                  "value": "image"
                }
              ]
            }
          }
        },
        {
          "name": "Get a file",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/media/med_381",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "media",
                "med_381"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Delete a file",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/media/med_381",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "media",
                "med_381"
              ]
            },
            "description": "Deletes the file and its public URL at once. If saved messages or templates still use it, the answer is `resource_in_use` listing them; add `?force=true` to delete anyway. Needs a live key, because the library is your live one."
          }
        }
      ]
    },
    {
      "name": "Contacts",
      "item": [
        {
          "name": "List custom contact fields",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contact_fields",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contact_fields"
              ]
            },
            "description": "The custom fields your contacts carry (created in Contacts → Fields). Use each `key` in a contact's `fields`."
          }
        },
        {
          "name": "List contacts",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts"
              ]
            },
            "description": "Your WhatsApp contacts, newest first. Find one person with `phone` (any format: `+966 50 123 4567`, `0501234567`…), or sync changes with `updated_since`."
          }
        },
        {
          "name": "Create a contact",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts"
              ]
            },
            "description": "One phone number is one contact: if the number already exists the answer is `resource_exists` with the `existing_id`. To create-or-update in one call, use `POST /v1/contacts/upsert`.\n\n`tags` takes tag ids or names; a name that does not exist yet is created. `fields` takes custom field values by `key` (see `GET /v1/contact_fields`).\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"+966501234567\",\n  \"first_name\": \"سارة\",\n  \"last_name\": \"القحطاني\",\n  \"email\": \"sara@example.com\",\n  \"language\": \"ar\",\n  \"tags\": [\n    \"عملاء VIP\"\n  ],\n  \"fields\": {\n    \"loyalty_points\": 120\n  },\n  \"consent\": {\n    \"source\": \"website_form\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Create or update a contact by phone",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts/upsert",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts",
                "upsert"
              ]
            },
            "description": "The call to keep your CRM and this workspace in step. Finds the contact by `phone` (in any format) and updates the fields you send, or creates it. `201` when created, `200` when updated.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"0501234567\",\n  \"first_name\": \"سارة\",\n  \"fields\": {\n    \"loyalty_points\": 180\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Get a contact",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts/ct_1052",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts",
                "ct_1052"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Update a contact",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts/ct_1052",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts",
                "ct_1052"
              ]
            },
            "description": "Changes only the fields you send. `tags` replaces the tag list (to add one, use `POST /v1/contacts/{id}/tags`); `fields` changes only the keys you send, and an empty value clears one.\n\n`opted_in: false` opts the contact out the way a STOP message does: queued campaign messages to them are cancelled. `opted_in: true` needs `consent` saying how they agreed.\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"city\": \"جدة\",\n  \"fields\": {\n    \"loyalty_points\": 200\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Delete a contact",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts/ct_1052",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts",
                "ct_1052"
              ]
            },
            "description": "Deletes the contact, its tags and custom field values. Campaign messages still queued for them are cancelled. The conversation history stays in the inbox."
          }
        },
        {
          "name": "Add tags to a contact",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts/ct_1052/tags",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts",
                "ct_1052",
                "tags"
              ]
            },
            "description": "Adds the tags (ids or names; a new name creates the tag) and keeps the ones the contact already has.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"tags\": [\n    \"tag_12\",\n    \"اشترى مؤخرًا\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Remove a tag from a contact",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/contacts/ct_1052/tags/tag_12",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "contacts",
                "ct_1052",
                "tags",
                "tag_12"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "List tags",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/tags",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "tags"
              ]
            },
            "description": "The tags that group your contacts, with how many WhatsApp contacts carry each one."
          }
        },
        {
          "name": "Create a tag",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/tags",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "tags"
              ]
            },
            "description": "",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"عملاء VIP\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Rename a tag",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/tags/tag_12",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "tags",
                "tag_12"
              ]
            },
            "description": "",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"عملاء ذهبيون\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Delete a tag",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/tags/tag_12",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "tags",
                "tag_12"
              ]
            },
            "description": "Removes the tag from every contact. The contacts stay."
          }
        }
      ]
    },
    {
      "name": "Conversations",
      "item": [
        {
          "name": "List conversations",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/conversations",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "conversations"
              ]
            },
            "description": "Threads in the shared inbox, newest first, on WhatsApp, Instagram and Messenger. Filter to build your own queue: `open=true&assignee=none` is everything waiting for someone."
          }
        },
        {
          "name": "Get a conversation",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/conversations/conv_311",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "conversations",
                "conv_311"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Assign a conversation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/conversations/conv_311/assign",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "conversations",
                "conv_311",
                "assign"
              ]
            },
            "description": "Hands the conversation to a team member. They must be able to see its number or account; viewers cannot be assigned.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"member_id\": \"usr_41\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "List a conversation's messages",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/conversations/conv_311/messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "conversations",
                "conv_311",
                "messages"
              ]
            },
            "description": "Every message in the thread, both directions, newest first. Internal notes between agents are never included."
          }
        },
        {
          "name": "Reopen a conversation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/conversations/conv_311/reopen",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "conversations",
                "conv_311",
                "reopen"
              ]
            },
            "description": "Reopens a resolved conversation, unassigned in the team queue, or assigned to `member_id`.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"member_id\": \"usr_41\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Resolve a conversation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/conversations/conv_311/resolve",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "conversations",
                "conv_311",
                "resolve"
              ]
            },
            "description": "Closes the conversation. If the customer writes again it reopens by itself, and you get `conversation.reopened`."
          }
        },
        {
          "name": "List team members",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/members",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "members"
              ]
            },
            "description": "The people in this workspace, to assign conversations to. Viewers can read the inbox but cannot be assigned."
          }
        }
      ]
    },
    {
      "name": "Campaigns",
      "item": [
        {
          "name": "List campaigns",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Create a campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns"
              ]
            },
            "description": "Creates a **draft**: nothing is sent until you call `POST /v1/campaigns/{id}/start`. The answer carries `estimated_cost`, the price WhatsApp will charge at today's rates, so you can confirm before sending.\n\n- **Audience**: `contacts` (ids), `tags` (ids or names), or `all_contacts: true`.\n- **Variables**: the template's values, where `{{first_name}}`, `{{last_name}}`, `{{phone_number}}` or any custom field key is filled in per recipient, e.g. `\"body\": [\"{{first_name}}\", \"20%\"]`.\n- **Consent**: if some recipients opted out of business messages, the answer is `recipient_not_consented` with the counts. Send `consent_confirmed: false` to skip them, or `true` only if they agreed again (your confirmation is recorded in the audit log).\n\nEvery check the campaign builder makes applies here too: a number Meta has limited cannot broadcast, the template must belong to the sending number, and the plan's monthly campaign and marketing-message allowances are enforced at start.\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"عرض نهاية الأسبوع\",\n  \"template\": {\n    \"name\": \"weekend_offer\",\n    \"language\": \"ar\"\n  },\n  \"number_id\": \"num_3\",\n  \"audience\": {\n    \"tags\": [\n      \"عملاء VIP\"\n    ]\n  },\n  \"variables\": {\n    \"body\": [\n      \"20٪\"\n    ]\n  },\n  \"scheduled_at\": \"2026-10-02T16:00:00\",\n  \"timezone\": \"Asia/Riyadh\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Get a campaign",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns/cmp_64",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns",
                "cmp_64"
              ]
            },
            "description": "The campaign with live results (sent, delivered, read, failed, replied and the rates)."
          }
        },
        {
          "name": "Cancel a campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns/cmp_64/cancel",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns",
                "cmp_64",
                "cancel"
              ]
            },
            "description": "Stops a scheduled or sending campaign. Messages already sent stay sent; the rest are cancelled."
          }
        },
        {
          "name": "List a campaign's recipients",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns/cmp_64/messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns",
                "cmp_64",
                "messages"
              ]
            },
            "description": "One `message` per recipient (`cmsg_…`), with its delivery status and, for a failure, WhatsApp's reason. Their status changes also arrive as `message.*` events."
          }
        },
        {
          "name": "Resume a paused campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns/cmp_64/resume",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns",
                "cmp_64",
                "resume"
              ]
            },
            "description": "Puts a held campaign back on the queue once its cause is fixed. Only ever by an explicit call, never by itself (except after a platform-wide pause), because a number just back from a restriction should not start broadcasting unattended. Refused while the number still cannot broadcast."
          }
        },
        {
          "name": "Start a campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/campaigns/cmp_64/start",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "campaigns",
                "cmp_64",
                "start"
              ]
            },
            "description": "Sends the draft now, or at its `scheduled_at`. Sending is paced to protect the number's quality rating; follow progress with `campaign.*` events and `GET /v1/campaigns/{id}`."
          }
        }
      ]
    },
    {
      "name": "Flows",
      "item": [
        {
          "name": "List WhatsApp Flow form responses",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/flow_responses",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "flow_responses"
              ]
            },
            "description": "Answers customers submitted in WhatsApp Flows (the forms that open inside the chat), newest first. Each new one also arrives as a `flow.response` event."
          }
        },
        {
          "name": "Get a flow run",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/flow_runs/id_123",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "flow_runs",
                "id_123"
              ]
            },
            "description": "Where one customer is in a flow, and the variables the flow has collected so far (answers, choices, values from your systems)."
          }
        },
        {
          "name": "List flows",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/flows",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "flows"
              ]
            },
            "description": "The automation flows built in the flow builder. `startable_via_api` marks the published flows with an \"API / webhook\" trigger, which `POST /v1/flows/{id}/runs` can start for a customer."
          }
        },
        {
          "name": "Get a flow",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/flows/flow_18",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "flows",
                "flow_18"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "List a flow's runs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/flows/flow_18/runs",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "flows",
                "flow_18",
                "runs"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Start a flow for a customer",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/flows/flow_18/runs",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "flows",
                "flow_18",
                "runs"
              ]
            },
            "description": "Runs the flow for one customer now, exactly as its \"API / webhook\" trigger would: the same steps, messages, waits and hand-offs. `variables` become the run's starting variables (the flow reads them as `{{name}}`), next to what it already knows about the contact. The customer comes from `to` only: `contact_id`, `contact_phone`, `phone`, `phone_number`, `customer` and keys starting with `_` are reserved and refused. `reference` is your own id, returned on the run and in every `flow.run.*` event.\n\nThe flow must be published with the \"API / webhook\" trigger (`startable_via_api: true`). Its first message follows WhatsApp's rules: outside the 24-hour window that means an approved template.\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to\": \"+966501234567\",\n  \"variables\": {\n    \"order_id\": \"10482\",\n    \"delivery_date\": \"الخميس\"\n  },\n  \"reference\": \"order-10482\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Usage",
      "item": [
        {
          "name": "Get usage",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/usage",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "usage"
              ]
            },
            "description": "What the workspace has used this billing period against its plan (marketing and service messages, campaigns, contacts, templates, flows, numbers), and how this key's mode has called the API over the last 30 days.\n\nCheck `remaining` before a large send to avoid a `quota_exceeded`. `limit` and `remaining` are `null` for an unlimited allowance.\n"
          }
        }
      ]
    },
    {
      "name": "Webhooks",
      "item": [
        {
          "name": "List event types",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/event_types",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "event_types"
              ]
            },
            "description": "Every event you can subscribe an endpoint to."
          }
        },
        {
          "name": "Retry a delivery now",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_deliveries/del_01j9x3k2m4n5p6q7r8s9t0v1w2/retry",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_deliveries",
                "del_01j9x3k2m4n5p6q7r8s9t0v1w2",
                "retry"
              ]
            },
            "description": "Sends the same event again (same `webhook-id`, fresh signature), e.g. after you fixed your server."
          }
        },
        {
          "name": "List webhook endpoints",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints"
              ]
            },
            "description": "The endpoints in the key's mode (live keys see live endpoints, test keys test endpoints)."
          }
        },
        {
          "name": "Add a webhook endpoint",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints"
              ]
            },
            "description": "We will POST each subscribed event to `url` as JSON, signed with the [Standard Webhooks](https://www.standardwebhooks.com) scheme. The response includes the signing `secret` **once**: store it to verify signatures.\n\nIn production the URL must be `https://` and publicly reachable. Up to 10 endpoints per workspace.\n\nAn event carries the same data its read endpoint returns, so each event family needs that read scope: `message.*` needs `messages:read`, `contact.*` `contacts:read`, `conversation.*` `conversations:read`, `campaign.*` `campaigns:read`, `flow.*` `flows:read`, `template.*` `templates:read`. `[\"*\"]` needs all of them. The same check applies when you change the URL or events of an endpoint.\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://example.com/webhooks/whatsapp\",\n  \"enabled_events\": [\n    \"message.received\",\n    \"message.delivered\",\n    \"message.read\",\n    \"message.failed\"\n  ],\n  \"description\": \"Order system\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Get a webhook endpoint",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints",
                "we_01j9x3k2m4n5p6q7r8s9t0v1w2"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Update a webhook endpoint",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints",
                "we_01j9x3k2m4n5p6q7r8s9t0v1w2"
              ]
            },
            "description": "Change the URL or events, or pause it with `\"disabled\": true`. Re-enabling clears the failure count.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"enabled_events\": [\n    \"*\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Delete a webhook endpoint",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints",
                "we_01j9x3k2m4n5p6q7r8s9t0v1w2"
              ]
            },
            "description": "Stops all deliveries to it, including pending retries."
          }
        },
        {
          "name": "List deliveries",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2/deliveries",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints",
                "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
                "deliveries"
              ]
            },
            "description": "Every attempt to deliver an event to this endpoint, newest first, with the HTTP status your server answered."
          }
        },
        {
          "name": "Rotate the signing secret",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2/rotate_secret",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints",
                "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
                "rotate_secret"
              ]
            },
            "description": "Returns a new `secret`. For 24 hours every event is signed with both the old and the new secret, so you can deploy the new one without missing events."
          }
        },
        {
          "name": "Send a test event",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2/test",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhook_endpoints",
                "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
                "test"
              ]
            },
            "description": "Sends a signed `webhook.test` event to this endpoint only. Check the delivery with the deliveries endpoint."
          }
        }
      ]
    },
    {
      "name": "Test mode",
      "item": [
        {
          "name": "Simulate a customer message",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/test/inbound_messages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "test",
                "inbound_messages"
              ]
            },
            "description": "As if a customer had just written to you. Fires `message.received` to your test endpoints and opens the simulated 24-hour window for that number. Test keys only.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"from\": \"+966500000004\",\n  \"type\": \"text\",\n  \"text\": {\n    \"body\": \"مرحبا، أين طلبي؟\"\n  },\n  \"profile_name\": \"Sara\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Force a message status",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/test/messages/msg_test_01j9x3k2m4n5p6q7r8s9t0v1w2/status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "test",
                "messages",
                "msg_test_01j9x3k2m4n5p6q7r8s9t0v1w2",
                "status"
              ]
            },
            "description": "Move a test message to `sent`, `delivered`, `read` or `failed` now and fire the matching event. Statuses only move forward. Test keys only.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"status\": \"failed\",\n  \"error_code\": \"131026\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    }
  ]
}