{
  "info": {
    "_postman_id": "9d9f1a2c-fb1a-4c3e-9f77-99d0facebook01",
    "name": "99digital - Facebook & Instagram API (v1)",
    "description": "Complete, runnable reference for the **99digital Facebook & Instagram API** (outgoing traffic, v1).\n\nEvery endpoint is here, and each one ships with **one sample per option** - text / photo album / video / scheduled post on Facebook, image / reel / story / carousel on Instagram, every button and chip type, every moderation action. Fill a few variables, press **Send**, and you are talking to production.\n\n---\n\n## Quick start\n\n1. **Variables tab** -> fill `apiKey` and the connection id(s) you were given: `from_fb_messenger`, `from_ig_messenger`, `from_fb_page`, `from_ig_page`.\n2. Fill the ids you want to work with - `psid` / `igsid` (recipients, always from *your* incoming webhook), `fb_post_id`, `ig_media_id`, ...\n3. Replace the `sample_*_url` variables with your own public https media (Meta downloads media from your server, so `example.com` will be rejected).\n4. Open a folder and press **Send**.\n\n`base_url` is `https://api.99digital.co.il`.\n\n## Authentication\n\nAll endpoints are **POST** with a JSON body (`Content-Type: application/json`).\n\n- The **`apiKey` goes in the request header** - this collection attaches it automatically to every request (collection-level auth), so it never appears in a body. An `apiKey` inside the body is ignored.\n- The **`from`** field (in the body) is the connection id - the `facebook_settings` document id, *not* the page id or instagram id.\n\n```\nContent-Type: application/json\napiKey: 2f080c-015335-d949da-691933-06ad82\n```\n\n## The four channel types\n\nEvery connection has a **`facebook_type`**, and each endpoint family serves exactly ONE of them. Calling an endpoint with a connection of the wrong type returns **reason 6** - the single most common integration mistake.\n\n| facebook_type | Name | Endpoint prefix | What it does |\n|---|---|---|---|\n| 1 | Facebook Messenger | `/facebook/messenger/` | DM with Facebook users (PSID) |\n| 2 | Instagram Messenger | `/instagram/messenger/` | DM with Instagram users (IGSID) |\n| 3 | Facebook Page | `/facebook/page/` | Page posts, comments, moderation, private replies, leads |\n| 4 | Instagram Page | `/instagram/page/` | IG publishing, comments, moderation, private replies |\n\nA client who wants both DMs and publishing needs **two connections** (and uses two different `from` values).\n\n## Two delivery models\n\n**A) Messenger DMs (types 1 + 2) - asynchronous.** High volume, so we validate, ack in ~1 second with a **`unique`** id, and call Meta in the background. The real Meta message id arrives afterwards as `meta_id` on your `sendStatus` webhook (folder *5*).\n\n**B) Page / posts / comments (types 3 + 4) - synchronous.** Low volume and you need the ids immediately, so there is no queue, no `unique` and no webhook - the response already carries the **real** `postId` / `mediaId` / `commentId`. Those are the same ids Meta uses and the same ids the read endpoints return: one id space, no translation.\n\n## Reading a response\n\n**Every response - success or failure - is HTTP 200.** Always read the JSON `status` field, never the HTTP code.\n\n```json\n{ \"status\": \"FAIL\", \"reason\": 10, \"from\": \"...\" }\n```\n\nWe never return Meta's numeric codes or raw messages. Every failure, including anything Meta rejects, is reported as one of OUR reason codes - key off the number and show your own text:\n\n| reason | Meaning | Typical cause / what to do |\n|---|---|---|\n| 1 | OK | - |\n| 2 | General error | Body is not valid JSON; `from` does not exist; internal error; could not reach Meta |\n| 3 | Invalid apiKey | The `apiKey` **header** is missing or does not match the connection's apiKey |\n| 4 | Missing/invalid target | `to` is not a valid numeric PSID/IGSID; `postId`/`commentId`/`mediaId` missing or malformed |\n| 5 | Missing/invalid content | No `body`; no `links`/`url`/`attachmentId`; a URL does not start with `http` |\n| 6 | Wrong connection type | The `from` connection's `facebook_type` does not match this endpoint family |\n| 7 | Connection not active | The connection's `status` is not 1 |\n| 8 | Invalid parameter value | Text too long, too many buttons/cards/chips, bad enum, `scheduleTime` out of range, `limit` out of 1-100 |\n| 10 | Access token invalid/expired | The connection must be re-onboarded |\n| 11 | Missing permission | The Page/app lacks the permission for this action |\n| 12 | Rate limited | Too many requests to Meta - wait and retry |\n| 13 | Target not found / inaccessible | The post/comment/media does not exist, was deleted, is not yours, or (privateReply) was already answered |\n| 14 | Cannot message recipient | The 24h window is closed or Meta will not deliver now |\n| 15 | Content rejected by Meta | Bad media format/size, invalid parameter, or policy violation |\n| 16 | Instagram daily publish limit | 100 API posts / 24h reached - try later |\n| 17 | Instagram media still processing | Nothing was published - retry the exact same request in ~1 minute |\n| 18 | Other Meta error | Any Meta rejection not covered above |\n\nCodes 2-8 are validation errors we catch before calling Meta; 10-18 are our translation of a Meta-side rejection. Reason 9 is not used.\n\n> Target/content validation runs **before** the apiKey check, so a bad `to` returns 4 even when the `apiKey` header is also wrong.\n\n## Id formats\n\n| Kind | Format | Where it comes from |\n|---|---|---|\n| PSID (FB user) | digits, e.g. `24031234567890123` | your incoming Messenger webhook - never guessed |\n| IGSID (IG user) | digits, e.g. `17841400000000000` | your incoming Instagram webhook |\n| Post id (FB) | `<pageid>_<postid>` | createPost / getPosts |\n| Comment id (FB) | `<postid>_<commentid>` | incoming webhook / getComments |\n| Media id (IG) | digits, e.g. `17895695668004550` | createPost / getPosts |\n| Comment id (IG) | digits, e.g. `17870913679156914` | incoming webhook / getComments |\n\nThis collection **captures those ids for you**: after a create or a read call, the returned id is written into the matching collection variable, so edit / hide / delete / getComments work with no copy-paste.\n\n## The 24-hour window (types 1 + 2)\n\n- You may DM a user only within **24 hours** of their last message to you. Outside it the send fails with **reason 14** (on the `sendStatus` webhook).\n- Message **tags are deprecated and not supported**.\n- Instagram DMs are **customer-initiated only** - you can never open a conversation.\n- Private replies (comment -> DM) are the exception: once per comment, within 7 days of it.\n\n## History\n\nEvery send / publish / moderation action (except `typing` and `sendReaction`) is written to our `facebook-history` store: `state` 0 = queued, 1 = accepted by Meta, -1 = failed. Messenger records are keyed by the `unique`; page records by the real Meta id. Records are deleted automatically after 1 year.\n\n---\n\nThis collection is generated from the running API, so the copy at **https://api.99digital.co.il/facebook-postman** is always in step with production - re-download it after any release note that touches the Facebook / Instagram endpoints. Re-importing updates this same collection instead of creating a duplicate.\n\nFull documentation: https://docs.99digital.co.il &nbsp;|&nbsp; Support: support@99digital.co.il",
    "version": "1.0.0",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "apiKey",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{apiKey}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// 99digital - Facebook & Instagram API",
          "// The apiKey is sent as an 'apiKey' HEADER on every request",
          "// (collection-level auth) - never inside the body.",
          "if (!pm.collectionVariables.get('apiKey')) {",
          "    console.warn('[99digital] The \"apiKey\" collection variable is empty - '",
          "        + 'every request will come back with reason 3. Fill it in the '",
          "        + 'collection Variables tab.');",
          "}"
        ]
      }
    },
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// 99digital - shared tests + automatic id capture.",
          "// Every response is HTTP 200: the real result is the JSON 'status' field.",
          "pm.test('HTTP 200', function () { pm.response.to.have.status(200); });",
          "",
          "var body = null;",
          "try { body = pm.response.json(); } catch (e) { body = null; }",
          "if (!body || typeof body !== 'object') { return; }",
          "",
          "if (body.status === 'OK') {",
          "    pm.test('status = OK (reason 1)', function () {",
          "        pm.expect(body.reason).to.eql(1);",
          "    });",
          "} else {",
          "    pm.test('FAIL - reason ' + body.reason, function () {",
          "        pm.expect.fail('The API returned reason ' + body.reason",
          "            + ' - look it up in the collection documentation.');",
          "    });",
          "}",
          "",
          "// --- id auto-capture: the follow-up requests just work ---",
          "var isIG = pm.request.url.toString().indexOf('/instagram/') !== -1;",
          "var set = function (key, value) {",
          "    if (value) { pm.collectionVariables.set(key, String(value)); }",
          "};",
          "",
          "// ids returned by the create / publish calls",
          "if (!isIG) { set('fb_post_id', body.postId); }",
          "set('ig_media_id', body.mediaId);",
          "if (isIG) { set('ig_comment_id', body.commentId); }",
          "else { set('fb_comment_id', body.commentId); }",
          "",
          "// ids returned by the read calls (first item of a list, or a single object)",
          "var firstPost = (body.posts && body.posts[0]) || body.post;",
          "if (firstPost && firstPost.id) {",
          "    set(isIG ? 'ig_media_id' : 'fb_post_id', firstPost.id);",
          "}",
          "var firstComment = body.comments && body.comments[0];",
          "if (firstComment && firstComment.id) {",
          "    set(isIG ? 'ig_comment_id' : 'fb_comment_id', firstComment.id);",
          "}",
          "",
          "// paging cursor for the '- next page' requests",
          "if (body.paging && body.paging.after) { set('after_cursor', body.paging.after); }"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.99digital.co.il",
      "type": "string",
      "description": "API host. Do not add a trailing slash."
    },
    {
      "key": "apiKey",
      "value": "",
      "type": "string",
      "description": "Your connection's apiKey (from onboarding). Sent as the `apiKey` HEADER on every request - the collection does that for you. Treat it as a password: switch this variable to the Postman type 'secret' if you share the collection inside a team workspace."
    },
    {
      "key": "from_fb_messenger",
      "value": "",
      "type": "string",
      "description": "Connection id of a facebook_type 1 (Facebook Messenger) connection."
    },
    {
      "key": "from_ig_messenger",
      "value": "",
      "type": "string",
      "description": "Connection id of a facebook_type 2 (Instagram Messenger) connection."
    },
    {
      "key": "from_fb_page",
      "value": "",
      "type": "string",
      "description": "Connection id of a facebook_type 3 (Facebook Page) connection."
    },
    {
      "key": "from_ig_page",
      "value": "",
      "type": "string",
      "description": "Connection id of a facebook_type 4 (Instagram Page) connection."
    },
    {
      "key": "psid",
      "value": "24031234567890123",
      "type": "string",
      "description": "Facebook user id (PSID) - taken from your incoming Messenger webhook."
    },
    {
      "key": "igsid",
      "value": "17841400000000000",
      "type": "string",
      "description": "Instagram user id (IGSID) - taken from your incoming Instagram webhook."
    },
    {
      "key": "fb_post_id",
      "value": "119324881085321_122093459712345",
      "type": "string",
      "description": "Facebook post id <page_id>_<post_id>. Auto-filled after createPost / getPosts."
    },
    {
      "key": "fb_comment_id",
      "value": "122093459712345_98765432109876",
      "type": "string",
      "description": "Facebook comment id. Auto-filled after createComment / getComments."
    },
    {
      "key": "fb_visitor_post_id",
      "value": "",
      "type": "string",
      "description": "A VISITOR post on your Page (published by a customer) - used by /facebook/page/privateReply. Not one of your own posts."
    },
    {
      "key": "fb_message_id",
      "value": "m_AbCdEfGhIjKlMnOpQrStUv",
      "type": "string",
      "description": "Messenger message id (m_...) - used by sendMessage `replyTo`."
    },
    {
      "key": "fb_attachment_id",
      "value": "1745504518999123",
      "type": "string",
      "description": "Reusable Facebook attachment id, returned by a sendFile with isReusable: 1."
    },
    {
      "key": "ig_media_id",
      "value": "17895695668004550",
      "type": "string",
      "description": "Instagram media id. Auto-filled after createPost / getPosts."
    },
    {
      "key": "ig_comment_id",
      "value": "17870913679156914",
      "type": "string",
      "description": "Instagram comment id. Auto-filled after createComment / getComments."
    },
    {
      "key": "ig_message_id",
      "value": "aWdfZG06MTpnaDoxMjM0NTY3ODkwOjM0",
      "type": "string",
      "description": "Instagram message id - from your incoming webhook. Used by sendReaction."
    },
    {
      "key": "leadgen_id",
      "value": "444444444444444",
      "type": "string",
      "description": "Lead id from Meta's `leadgen` webhook - used by /facebook/page/getLead."
    },
    {
      "key": "after_cursor",
      "value": "",
      "type": "string",
      "description": "Paging cursor. Auto-filled from paging.after of the last list response."
    },
    {
      "key": "schedule_time",
      "value": "",
      "type": "string",
      "description": "UNIX seconds for a scheduled Facebook post (11 min - 30 days ahead). The 'Scheduled ...' samples fill it with now + 1 hour in their pre-request script."
    },
    {
      "key": "sample_image_url",
      "value": "https://example.com/photo.jpg",
      "type": "string",
      "description": "REPLACE ME. A public https image URL - Meta downloads it from your server. Instagram: JPEG only, <=8MB, ratio 4:5-1.91:1, width 320-1440."
    },
    {
      "key": "sample_image_url_2",
      "value": "https://example.com/photo-2.jpg",
      "type": "string",
      "description": "REPLACE ME. Second image, for albums / carousels."
    },
    {
      "key": "sample_video_url",
      "value": "https://example.com/video.mp4",
      "type": "string",
      "description": "REPLACE ME. A public https video URL (mp4/mov)."
    },
    {
      "key": "sample_audio_url",
      "value": "https://example.com/audio.mp3",
      "type": "string",
      "description": "REPLACE ME. A public https audio URL."
    },
    {
      "key": "sample_file_url",
      "value": "https://example.com/price-list.pdf",
      "type": "string",
      "description": "REPLACE ME. A public https document URL."
    },
    {
      "key": "sample_cover_url",
      "value": "https://example.com/reel-cover.jpg",
      "type": "string",
      "description": "REPLACE ME. Cover image for an Instagram reel."
    },
    {
      "key": "sample_fb_hosted_url",
      "value": "https://www.facebook.com/some/facebook/hosted/media.jpg",
      "type": "string",
      "description": "Facebook-hosted media URL (must contain facebook.com) for sendMediaTemplate."
    },
    {
      "key": "your_webhook_url",
      "value": "https://your-server.example.com/99digital/facebook-webhook",
      "type": "string",
      "description": "Only used by the '5 - Webhooks' folder, to POST a sample payload at your own server so you can test your webhook handler."
    }
  ],
  "item": [
    {
      "name": "0 - Start here",
      "description": "**Three steps and you can send.**\n\n1. Open the collection **Variables** tab and fill `apiKey` plus the connection id(s) you were given (`from_fb_messenger`, `from_ig_messenger`, `from_fb_page`, `from_ig_page`) - one per `facebook_type` you onboarded.\n2. Fill the recipient/object ids you want to work with (`psid`, `igsid`, `fb_post_id`, `ig_media_id`, ...). Recipient ids always come from **your incoming webhook** - they can never be guessed.\n3. Replace the `sample_*_url` variables with your own public https media.\n\nThe `apiKey` is attached as a **header** on every request automatically (collection-level auth), so it never appears in a body.\n\nThis collection also **auto-fills ids for you**: after a createPost, createComment or a getPosts/getComments call, the returned `postId` / `mediaId` / `commentId` is written back into the matching collection variable, so the follow-up requests (edit, hide, delete, getComments...) work with no copy-paste.",
      "item": [
        {
          "name": "Connectivity check",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/",
              "host": [
                "{{base_url}}"
              ],
              "path": []
            },
            "description": "Plain `GET https://api.99digital.co.il/` - returns a small HTML page. Use it only to prove the host is reachable from your network; it is not an API endpoint and needs no apiKey.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "1 - Facebook Messenger (type 1)",
      "description": "Requires a **`facebook_type: 1`** connection (`{{from_fb_messenger}}`).\n\n- `to` is always a **PSID** (digits) taken from your incoming Messenger webhook.\n- Text is **plain text** - no markdown/HTML. Emojis and `\\n` line breaks are fine.\n- You may DM a user only within **24 hours** of their last message (outside it: reason 14 on the webhook). Message tags are not supported.\n- All sends are **asynchronous**: `OK` + `unique` now, `meta_id` later on the `sendStatus` webhook.\n\nAlso accepted on this endpoint: `notificationType` (`REGULAR` / `SILENT_PUSH` / `NO_PUSH`) and `metadata` (free text <=1000 chars, echoed back on the `message_echoes` webhook).",
      "item": [
        {
          "name": "sendMessage",
          "description": "`POST /facebook/messenger/sendMessage` - plain text, 1-2000 chars.",
          "item": [
            {
              "name": "Text message",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Hello from 99digital 👋\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMessage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMessage"
                  ]
                },
                "description": "The minimal send: `from`, `to`, `body`.\n\n| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | PSID, digits only -> else reason 4 |\n| `body` | yes | 1-2000 chars. Missing -> 5, over 2000 -> 8 |\n| `replyTo` | no | A message id (`m_...`) to quote |\n| `messagingType` | no | `RESPONSE` (default) / `UPDATE` |\n| `notificationType` | no | `REGULAR` / `SILENT_PUSH` / `NO_PUSH` |\n| `metadata` | no | <=1000 chars, echoed on `message_echoes` |\n| `showRequest` | no | `1` = echo your request back in the response |\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Hello from 99digital 👋\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendMessage",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendMessage"
                      ]
                    },
                    "description": "The minimal send: `from`, `to`, `body`.\n\n| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | PSID, digits only -> else reason 4 |\n| `body` | yes | 1-2000 chars. Missing -> 5, over 2000 -> 8 |\n| `replyTo` | no | A message id (`m_...`) to quote |\n| `messagingType` | no | `RESPONSE` (default) / `UPDATE` |\n| `notificationType` | no | `REGULAR` / `SILENT_PUSH` / `NO_PUSH` |\n| `metadata` | no | <=1000 chars, echoed on `message_echoes` |\n| `showRequest` | no | `1` = echo your request back in the response |\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"body\": \"Hello from 99digital 👋\"\n}"
                },
                {
                  "name": "Failure - invalid apiKey header",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Hello from 99digital 👋\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendMessage",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendMessage"
                      ]
                    },
                    "description": "The minimal send: `from`, `to`, `body`.\n\n| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | PSID, digits only -> else reason 4 |\n| `body` | yes | 1-2000 chars. Missing -> 5, over 2000 -> 8 |\n| `replyTo` | no | A message id (`m_...`) to quote |\n| `messagingType` | no | `RESPONSE` (default) / `UPDATE` |\n| `notificationType` | no | `REGULAR` / `SILENT_PUSH` / `NO_PUSH` |\n| `metadata` | no | <=1000 chars, echoed on `message_echoes` |\n| `showRequest` | no | `1` = echo your request back in the response |\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"FAIL\",\n  \"reason\": 3\n}"
                },
                {
                  "name": "Failure - wrong connection type (not type 1)",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Hello from 99digital 👋\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendMessage",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendMessage"
                      ]
                    },
                    "description": "The minimal send: `from`, `to`, `body`.\n\n| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | PSID, digits only -> else reason 4 |\n| `body` | yes | 1-2000 chars. Missing -> 5, over 2000 -> 8 |\n| `replyTo` | no | A message id (`m_...`) to quote |\n| `messagingType` | no | `RESPONSE` (default) / `UPDATE` |\n| `notificationType` | no | `REGULAR` / `SILENT_PUSH` / `NO_PUSH` |\n| `metadata` | no | <=1000 chars, echoed on `message_echoes` |\n| `showRequest` | no | `1` = echo your request back in the response |\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"FAIL\",\n  \"reason\": 6\n}"
                }
              ]
            },
            {
              "name": "Text message - multi line",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Order #12345 confirmed ✅\\nPickup: today until 18:00\\nAddress: Herzl 1, Tel Aviv\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMessage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMessage"
                  ]
                },
                "description": "Use real `\\n` line breaks inside the JSON string. Markdown is NOT rendered by Messenger - `*bold*` shows up literally."
              },
              "response": []
            },
            {
              "name": "Reply to a message (quote bubble)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Yes, that item is in stock.\",\n  \"replyTo\": \"{{fb_message_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMessage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMessage"
                  ]
                },
                "description": "`replyTo` takes the Messenger message id (`m_...`) of the customer message you are answering - it comes from your incoming webhook. The message is shown as a quoted reply."
              },
              "response": []
            },
            {
              "name": "All optional fields",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Your delivery is on the way 🚚\",\n  \"messagingType\": \"UPDATE\",\n  \"notificationType\": \"SILENT_PUSH\",\n  \"metadata\": \"order-12345\",\n  \"showRequest\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMessage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMessage"
                  ]
                },
                "description": "Everything at once.\n\n- `messagingType: UPDATE` - a proactive message inside the 24h window (`RESPONSE` is the default and fits replies).\n- `notificationType: SILENT_PUSH` - arrives without a push sound; `NO_PUSH` = no notification at all.\n- `metadata` - your own correlation string, echoed back on the `message_echoes` webhook.\n- `showRequest: 1` - the response repeats what you sent, handy while integrating.\n\nA bad enum value in any of them returns reason 8."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Your delivery is on the way 🚚\",\n  \"messagingType\": \"UPDATE\",\n  \"notificationType\": \"SILENT_PUSH\",\n  \"metadata\": \"order-12345\",\n  \"showRequest\": 1\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendMessage",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendMessage"
                      ]
                    },
                    "description": "Everything at once.\n\n- `messagingType: UPDATE` - a proactive message inside the 24h window (`RESPONSE` is the default and fits replies).\n- `notificationType: SILENT_PUSH` - arrives without a push sound; `NO_PUSH` = no notification at all.\n- `metadata` - your own correlation string, echoed back on the `message_echoes` webhook.\n- `showRequest: 1` - the response repeats what you sent, handy while integrating.\n\nA bad enum value in any of them returns reason 8."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"body\": \"Your delivery is on the way 🚚\",\n  \"originalRequest\": {\n    \"from\": \"{{from_fb_messenger}}\",\n    \"to\": \"24031234567890123\",\n    \"body\": \"Your delivery is on the way 🚚\"\n  }\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "sendFile",
          "description": "`POST /facebook/messenger/sendFile` - image / audio / video / document, up to **25MB** (Meta limit).\n\n> Media must be a **public https URL that Meta can download**. Replace the `{{sample_*_url}}` variables with your own files - the `example.com` defaults will be rejected by Meta (reason 15 / 18).",
          "item": [
            {
              "name": "Image",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"url\": \"{{sample_image_url}}\",\n  \"type\": \"image\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `url` | yes (or `attachmentId`) | Public https URL. Neither -> 5; not starting `http` -> 5 |\n| `attachmentId` | yes (or `url`) | Reusable id from a previous `isReusable` send |\n| `type` | no | `image` / `audio` / `video` / `file`. Omit it and we infer from the URL extension. Bad value -> 8 |\n| `isReusable` | no (0) | `1` = Meta returns a reusable attachment id |\n\n> Messenger attachments have **no caption** - send a separate text message if you need one.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"url\": \"{{sample_image_url}}\",\n  \"type\": \"image\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendFile",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendFile"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `url` | yes (or `attachmentId`) | Public https URL. Neither -> 5; not starting `http` -> 5 |\n| `attachmentId` | yes (or `url`) | Reusable id from a previous `isReusable` send |\n| `type` | no | `image` / `audio` / `video` / `file`. Omit it and we infer from the URL extension. Bad value -> 8 |\n| `isReusable` | no (0) | `1` = Meta returns a reusable attachment id |\n\n> Messenger attachments have **no caption** - send a separate text message if you need one.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"type\": \"image\"\n}"
                }
              ]
            },
            {
              "name": "Image - reusable (cache the attachment)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"url\": \"{{sample_image_url}}\",\n  \"type\": \"image\",\n  \"isReusable\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "With `isReusable: 1` Meta stores the upload and returns an **attachment id** on the `sendStatus` webhook. Save it into the `fb_attachment_id` variable and re-send the same media instantly (no re-upload, no bandwidth) with the *By attachmentId* request below. Recommended for logos, catalogue images and any file you send often."
              },
              "response": []
            },
            {
              "name": "Video",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"url\": \"{{sample_video_url}}\",\n  \"type\": \"video\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "mp4 / mov / avi / webm / 3gp, up to 25MB."
              },
              "response": []
            },
            {
              "name": "Audio",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"url\": \"{{sample_audio_url}}\",\n  \"type\": \"audio\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "mp3 / ogg / wav / m4a / aac - shown as a playable voice bubble."
              },
              "response": []
            },
            {
              "name": "Document (pdf, docx, xlsx...)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"url\": \"{{sample_file_url}}\",\n  \"type\": \"file\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "Anything that is not image/audio/video. `type` may be omitted - an unknown extension is inferred as `file`."
              },
              "response": []
            },
            {
              "name": "By attachmentId (no re-upload)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"attachmentId\": \"{{fb_attachment_id}}\",\n  \"type\": \"image\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "Send a previously uploaded file by its reusable id. Fastest option and it never re-downloads your server."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendQuickReplies",
          "description": "`POST /facebook/messenger/sendQuickReplies` - a text bubble plus up to **13 chips** above the composer. Chips vanish once the user taps one, and the tapped `payload` arrives on your incoming webhook.",
          "item": [
            {
              "name": "Text chips",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"How can we help?\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Track my order\",\n      \"payload\": \"TRACK_ORDER\"\n    },\n    {\n      \"title\": \"Open a ticket\",\n      \"payload\": \"NEW_TICKET\"\n    },\n    {\n      \"title\": \"Talk to a human\",\n      \"payload\": \"TALK_HUMAN\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendQuickReplies",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendQuickReplies"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `body` | yes | 1-2000 chars |\n| `quickReplies` | yes | 1-13 items -> else reason 8 |\n\nChip: `title` (mandatory, <=20 chars), `payload` (optional, defaults to the title), `imageUrl` (optional icon). A missing or >20-char title returns reason 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"How can we help?\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Track my order\",\n      \"payload\": \"TRACK_ORDER\"\n    },\n    {\n      \"title\": \"Open a ticket\",\n      \"payload\": \"NEW_TICKET\"\n    },\n    {\n      \"title\": \"Talk to a human\",\n      \"payload\": \"TALK_HUMAN\"\n    }\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendQuickReplies",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendQuickReplies"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `body` | yes | 1-2000 chars |\n| `quickReplies` | yes | 1-13 items -> else reason 8 |\n\nChip: `title` (mandatory, <=20 chars), `payload` (optional, defaults to the title), `imageUrl` (optional icon). A missing or >20-char title returns reason 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"body\": \"How can we help?\"\n}"
                }
              ]
            },
            {
              "name": "Chips with icons",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Pick a colour:\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Red\",\n      \"payload\": \"COLOR_RED\",\n      \"imageUrl\": \"{{sample_image_url}}\"\n    },\n    {\n      \"title\": \"Blue\",\n      \"payload\": \"COLOR_BLUE\",\n      \"imageUrl\": \"{{sample_image_url_2}}\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendQuickReplies",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendQuickReplies"
                  ]
                },
                "description": "`imageUrl` puts a small icon inside the chip (Facebook only - Instagram chips are text-only)."
              },
              "response": []
            },
            {
              "name": "Phone & email chips (one-tap share)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Leave your details and we'll call you back:\",\n  \"quickReplies\": [\n    {\n      \"type\": \"phone\"\n    },\n    {\n      \"type\": \"email\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendQuickReplies",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendQuickReplies"
                  ]
                },
                "description": "`{\"type\": \"phone\"}` / `{\"type\": \"email\"}` let the user share the phone/email on their Facebook profile with a single tap - the value arrives on your incoming webhook. Facebook only."
              },
              "response": []
            },
            {
              "name": "Mixed chips",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Almost done - choose one:\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Yes, continue\",\n      \"payload\": \"YES\"\n    },\n    {\n      \"title\": \"No thanks\"\n    },\n    {\n      \"type\": \"phone\"\n    },\n    {\n      \"type\": \"email\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendQuickReplies",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendQuickReplies"
                  ]
                },
                "description": "Text, phone and email chips can be mixed freely inside the same 13-item limit. `No thanks` has no `payload`, so the title itself comes back as the payload."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendButtons",
          "description": "`POST /facebook/messenger/sendButtons` - button template: a text bubble with up to **3 buttons**. Facebook only (on Instagram use sendCarousel).",
          "item": [
            {
              "name": "URL button",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Your invoice is ready.\",\n  \"buttons\": [\n    {\n      \"type\": \"url\",\n      \"title\": \"View invoice\",\n      \"url\": \"https://example.com/invoice/12345\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendButtons",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendButtons"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `body` | yes | 1-**640** chars (missing -> 5, over -> 8) |\n| `buttons` | yes | 1-3 buttons -> else 8 |\n\nButton types: `url` (`title` <=20 + `url` starting `http`), `postback` (`title` + `payload`), `call` (`title` + `phone`). Any other type, a missing title or a bad url returns reason 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Your invoice is ready.\",\n  \"buttons\": [\n    {\n      \"type\": \"url\",\n      \"title\": \"View invoice\",\n      \"url\": \"https://example.com/invoice/12345\"\n    }\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendButtons",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendButtons"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `body` | yes | 1-**640** chars (missing -> 5, over -> 8) |\n| `buttons` | yes | 1-3 buttons -> else 8 |\n\nButton types: `url` (`title` <=20 + `url` starting `http`), `postback` (`title` + `payload`), `call` (`title` + `phone`). Any other type, a missing title or a bad url returns reason 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"body\": \"Your invoice is ready.\"\n}"
                }
              ]
            },
            {
              "name": "Postback button",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Did that solve your problem?\",\n  \"buttons\": [\n    {\n      \"type\": \"postback\",\n      \"title\": \"Yes, thanks\",\n      \"payload\": \"SOLVED_YES\"\n    },\n    {\n      \"type\": \"postback\",\n      \"title\": \"Still stuck\",\n      \"payload\": \"SOLVED_NO\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendButtons",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendButtons"
                  ]
                },
                "description": "A `postback` button sends its `payload` to your incoming webhook - the way to drive a bot flow. Omit `payload` and the title is used."
              },
              "response": []
            },
            {
              "name": "Call button",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"Prefer to talk? Our line is open until 18:00.\",\n  \"buttons\": [\n    {\n      \"type\": \"call\",\n      \"title\": \"Call us\",\n      \"phone\": \"+972500000000\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendButtons",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendButtons"
                  ]
                },
                "description": "`phone` must be international; the leading `+` is added automatically if you omit it. Facebook only - a `call` button on Instagram returns reason 8."
              },
              "response": []
            },
            {
              "name": "All three types together",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"body\": \"What would you like to do?\",\n  \"buttons\": [\n    {\n      \"type\": \"url\",\n      \"title\": \"Our catalogue\",\n      \"url\": \"https://example.com/catalogue\"\n    },\n    {\n      \"type\": \"postback\",\n      \"title\": \"Talk to us\",\n      \"payload\": \"TALK_HUMAN\"\n    },\n    {\n      \"type\": \"call\",\n      \"title\": \"Call us\",\n      \"phone\": \"+972500000000\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendButtons",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendButtons"
                  ]
                },
                "description": "3 buttons is the hard maximum - a 4th returns reason 8."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendCarousel",
          "description": "`POST /facebook/messenger/sendCarousel` - generic template: up to **10 horizontally scrollable cards**, each with its own image, texts and up to 3 buttons.\n\n> Media must be a **public https URL that Meta can download**. Replace the `{{sample_*_url}}` variables with your own files - the `example.com` defaults will be rejected by Meta (reason 15 / 18).",
          "item": [
            {
              "name": "Two cards with buttons",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"aspectRatio\": \"horizontal\",\n  \"cards\": [\n    {\n      \"title\": \"Running shoes\",\n      \"subtitle\": \"299 NIS - free shipping\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"defaultUrl\": \"https://example.com/p/shoes\",\n      \"buttons\": [\n        {\n          \"type\": \"url\",\n          \"title\": \"Buy now\",\n          \"url\": \"https://example.com/p/shoes\"\n        },\n        {\n          \"type\": \"postback\",\n          \"title\": \"More info\",\n          \"payload\": \"INFO_SHOES\"\n        }\n      ]\n    },\n    {\n      \"title\": \"Sports socks\",\n      \"subtitle\": \"39 NIS\",\n      \"imageUrl\": \"{{sample_image_url_2}}\",\n      \"defaultUrl\": \"https://example.com/p/socks\",\n      \"buttons\": [\n        {\n          \"type\": \"url\",\n          \"title\": \"Buy now\",\n          \"url\": \"https://example.com/p/socks\"\n        }\n      ]\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendCarousel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendCarousel"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `cards` | yes | 1-10 cards -> else reason 8 |\n| `aspectRatio` | no | `horizontal` (default, 1.91:1) or `square` |\n\nCard: `title` (mandatory, <=80), `subtitle` (<=80), `imageUrl`, `defaultUrl` (opened when the card itself is tapped), `buttons` (up to 3, same types as sendButtons).\n\nThe success response echoes `cards` as a **count**.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"aspectRatio\": \"horizontal\",\n  \"cards\": [\n    {\n      \"title\": \"Running shoes\",\n      \"subtitle\": \"299 NIS - free shipping\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"defaultUrl\": \"https://example.com/p/shoes\",\n      \"buttons\": [\n        {\n          \"type\": \"url\",\n          \"title\": \"Buy now\",\n          \"url\": \"https://example.com/p/shoes\"\n        },\n        {\n          \"type\": \"postback\",\n          \"title\": \"More info\",\n          \"payload\": \"INFO_SHOES\"\n        }\n      ]\n    },\n    {\n      \"title\": \"Sports socks\",\n      \"subtitle\": \"39 NIS\",\n      \"imageUrl\": \"{{sample_image_url_2}}\",\n      \"defaultUrl\": \"https://example.com/p/socks\",\n      \"buttons\": [\n        {\n          \"type\": \"url\",\n          \"title\": \"Buy now\",\n          \"url\": \"https://example.com/p/socks\"\n        }\n      ]\n    }\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendCarousel",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendCarousel"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `cards` | yes | 1-10 cards -> else reason 8 |\n| `aspectRatio` | no | `horizontal` (default, 1.91:1) or `square` |\n\nCard: `title` (mandatory, <=80), `subtitle` (<=80), `imageUrl`, `defaultUrl` (opened when the card itself is tapped), `buttons` (up to 3, same types as sendButtons).\n\nThe success response echoes `cards` as a **count**.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"cards\": 2\n}"
                }
              ]
            },
            {
              "name": "Square images",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"aspectRatio\": \"square\",\n  \"cards\": [\n    {\n      \"title\": \"Product A\",\n      \"subtitle\": \"In stock\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"buttons\": [\n        {\n          \"type\": \"postback\",\n          \"title\": \"Choose\",\n          \"payload\": \"PICK_A\"\n        }\n      ]\n    },\n    {\n      \"title\": \"Product B\",\n      \"subtitle\": \"In stock\",\n      \"imageUrl\": \"{{sample_image_url_2}}\",\n      \"buttons\": [\n        {\n          \"type\": \"postback\",\n          \"title\": \"Choose\",\n          \"payload\": \"PICK_B\"\n        }\n      ]\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendCarousel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendCarousel"
                  ]
                },
                "description": "`square` crops the card images 1:1 instead of 1.91:1. Any other value returns reason 8."
              },
              "response": []
            },
            {
              "name": "Tappable cards, no buttons",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"cards\": [\n    {\n      \"title\": \"Summer collection\",\n      \"subtitle\": \"42 new items\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"defaultUrl\": \"https://example.com/summer\"\n    },\n    {\n      \"title\": \"Winter collection\",\n      \"subtitle\": \"Coming soon\",\n      \"imageUrl\": \"{{sample_image_url_2}}\",\n      \"defaultUrl\": \"https://example.com/winter\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendCarousel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendCarousel"
                  ]
                },
                "description": "`buttons` is optional - with only `defaultUrl` the whole card becomes one big link."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendMediaTemplate",
          "description": "`POST /facebook/messenger/sendMediaTemplate` - an image/video bubble with buttons.\n\n> ⚠️ The media must be **Facebook-hosted**: either an `attachmentId`, or a `url` that contains `facebook.com`. Any other URL returns reason 8 - that is Meta's restriction, use **sendFile** for external media.",
          "item": [
            {
              "name": "Image by attachmentId",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"mediaType\": \"image\",\n  \"attachmentId\": \"{{fb_attachment_id}}\",\n  \"buttons\": [\n    {\n      \"type\": \"url\",\n      \"title\": \"Buy\",\n      \"url\": \"https://example.com/p/1\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMediaTemplate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMediaTemplate"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaType` | no (`image`) | `image` or `video` -> else 8 |\n| `attachmentId` | yes (or `url`) | Reusable Facebook attachment id |\n| `url` | yes (or `attachmentId`) | Must contain `facebook.com` -> else 8. Neither given -> 5 |\n| `buttons` | no | Up to 3, same types as sendButtons |\n\nGet an `attachmentId` by sending the file once with `sendFile` + `isReusable: 1`.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"mediaType\": \"image\",\n  \"attachmentId\": \"{{fb_attachment_id}}\",\n  \"buttons\": [\n    {\n      \"type\": \"url\",\n      \"title\": \"Buy\",\n      \"url\": \"https://example.com/p/1\"\n    }\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/sendMediaTemplate",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "sendMediaTemplate"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaType` | no (`image`) | `image` or `video` -> else 8 |\n| `attachmentId` | yes (or `url`) | Reusable Facebook attachment id |\n| `url` | yes (or `attachmentId`) | Must contain `facebook.com` -> else 8. Neither given -> 5 |\n| `buttons` | no | Up to 3, same types as sendButtons |\n\nGet an `attachmentId` by sending the file once with `sendFile` + `isReusable: 1`.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"mediaType\": \"image\"\n}"
                }
              ]
            },
            {
              "name": "Video by attachmentId",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"mediaType\": \"video\",\n  \"attachmentId\": \"{{fb_attachment_id}}\",\n  \"buttons\": [\n    {\n      \"type\": \"postback\",\n      \"title\": \"I want this\",\n      \"payload\": \"WANT_IT\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMediaTemplate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMediaTemplate"
                  ]
                },
                "description": "Same call with `mediaType: video`. The attachment must have been uploaded as a video."
              },
              "response": []
            },
            {
              "name": "Facebook-hosted URL",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"mediaType\": \"image\",\n  \"url\": \"{{sample_fb_hosted_url}}\",\n  \"buttons\": [\n    {\n      \"type\": \"url\",\n      \"title\": \"Open\",\n      \"url\": \"https://example.com\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/sendMediaTemplate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "sendMediaTemplate"
                  ]
                },
                "description": "Only URLs containing `facebook.com` are accepted here (e.g. a photo already published on your Page). Anything else -> reason 8."
              },
              "response": []
            }
          ]
        },
        {
          "name": "typing",
          "description": "`POST /facebook/messenger/typing` - sender actions. **Not written to history.**",
          "item": [
            {
              "name": "typing_on",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"action\": \"typing_on\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/typing",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "typing"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `action` | no (`typing_on`) | `typing_on` / `typing_off` / `mark_seen` -> else reason 8 |\n\nTyping indicators auto-expire after ~20 seconds on Meta's side, so there is usually no need to send `typing_off`.\n\nFailures: 2, 3, 4, 6, 7, 8."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"action\": \"typing_on\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/messenger/typing",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "messenger",
                        "typing"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `action` | no (`typing_on`) | `typing_on` / `typing_off` / `mark_seen` -> else reason 8 |\n\nTyping indicators auto-expire after ~20 seconds on Meta's side, so there is usually no need to send `typing_off`.\n\nFailures: 2, 3, 4, 6, 7, 8."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_fb_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"24031234567890123\",\n  \"action\": \"typing_on\"\n}"
                }
              ]
            },
            {
              "name": "typing_off",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"action\": \"typing_off\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/typing",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "typing"
                  ]
                },
                "description": "Clears the indicator early."
              },
              "response": []
            },
            {
              "name": "mark_seen",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_messenger}}\",\n  \"to\": \"{{psid}}\",\n  \"action\": \"mark_seen\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/messenger/typing",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "messenger",
                    "typing"
                  ]
                },
                "description": "Marks the customer's last message as read (the blue seen mark)."
              },
              "response": []
            }
          ]
        }
      ]
    },
    {
      "name": "2 - Instagram Messenger (type 2)",
      "description": "Requires a **`facebook_type: 2`** connection (`{{from_ig_messenger}}`).\n\n`to` is always an **IGSID** (digits) from your incoming Instagram webhook.\n\nInstagram DMs are a **subset** of Facebook Messenger:\n\n| Difference vs type 1 | Detail |\n|---|---|\n| Text limit | **1000 bytes** (not 2000 chars) - Hebrew/emoji take 2-4 bytes per character |\n| Quick replies | Text-only: no icons, no phone/email chips, and they render in the **IG mobile app only** |\n| No button template, no media template | Use `sendCarousel` with buttons |\n| Not supported | `replyTo`, `messagingType`, `notificationType`, `metadata`, `aspectRatio` |\n| Extra features | `sendReaction`, `sendMediaShare` |\n| Media | Images PNG/JPEG <=8MB, video <=25MB |\n\n**Customer-initiated only** - you can never open a conversation, and you may answer only within the 24h window (outside it: reason 14 on the webhook).",
      "item": [
        {
          "name": "sendMessage",
          "description": "`POST /instagram/messenger/sendMessage` - plain text, **<=1000 bytes UTF-8**.",
          "item": [
            {
              "name": "Text message",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"Hi! Thanks for reaching out 🙌\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendMessage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendMessage"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | IGSID -> else reason 4 |\n| `body` | yes | <=**1000 bytes** UTF-8. Missing -> 5, over -> 8 |\n| `showRequest` | no | `1` = echo your request in the response |\n\n> The limit is in **bytes**, not characters: Hebrew is 2 bytes per character and most emojis are 4.\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"Hi! Thanks for reaching out 🙌\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendMessage",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendMessage"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | IGSID -> else reason 4 |\n| `body` | yes | <=**1000 bytes** UTF-8. Missing -> 5, over -> 8 |\n| `showRequest` | no | `1` = echo your request in the response |\n\n> The limit is in **bytes**, not characters: Hebrew is 2 bytes per character and most emojis are 4.\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"body\": \"Hi! Thanks for reaching out 🙌\"\n}"
                },
                {
                  "name": "Failure - body over 1000 bytes",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"Hi! Thanks for reaching out 🙌\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendMessage",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendMessage"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `to` | yes | IGSID -> else reason 4 |\n| `body` | yes | <=**1000 bytes** UTF-8. Missing -> 5, over -> 8 |\n| `showRequest` | no | `1` = echo your request in the response |\n\n> The limit is in **bytes**, not characters: Hebrew is 2 bytes per character and most emojis are 4.\n\nFailures: 2, 3, 4, 5, 6, 7, 8.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"FAIL\",\n  \"reason\": 8\n}"
                }
              ]
            },
            {
              "name": "Text message + echo the request",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"Your order is ready for pickup ✅\",\n  \"showRequest\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendMessage",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendMessage"
                  ]
                },
                "description": "`showRequest: 1` adds an `originalRequest` object to the response - useful while integrating, drop it in production."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendFile",
          "description": "`POST /instagram/messenger/sendFile` - image / video / audio / file.\n\n> Media must be a **public https URL that Meta can download**. Replace the `{{sample_*_url}}` variables with your own files - the `example.com` defaults will be rejected by Meta (reason 15 / 18).",
          "item": [
            {
              "name": "Image",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"url\": \"{{sample_image_url}}\",\n  \"type\": \"image\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `url` | yes (or `attachmentId`) | Must start `http` -> else 5 |\n| `attachmentId` | yes (or `url`) | Reusable attachment id |\n| `type` | no | `image` (PNG/JPEG <=8MB) / `video` (MP4/MOV <=25MB) / `audio` / `file`. Omit to infer from the extension. Bad value -> 8 |\n\nGIF is not officially supported by Instagram.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"url\": \"{{sample_image_url}}\",\n  \"type\": \"image\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendFile",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendFile"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `url` | yes (or `attachmentId`) | Must start `http` -> else 5 |\n| `attachmentId` | yes (or `url`) | Reusable attachment id |\n| `type` | no | `image` (PNG/JPEG <=8MB) / `video` (MP4/MOV <=25MB) / `audio` / `file`. Omit to infer from the extension. Bad value -> 8 |\n\nGIF is not officially supported by Instagram.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"type\": \"image\"\n}"
                }
              ]
            },
            {
              "name": "Video",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"url\": \"{{sample_video_url}}\",\n  \"type\": \"video\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "MP4 / MOV up to 25MB."
              },
              "response": []
            },
            {
              "name": "Audio",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"url\": \"{{sample_audio_url}}\",\n  \"type\": \"audio\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "Sent as a playable audio bubble."
              },
              "response": []
            },
            {
              "name": "By attachmentId",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"attachmentId\": \"{{fb_attachment_id}}\",\n  \"type\": \"image\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendFile",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendFile"
                  ]
                },
                "description": "Re-send an already uploaded file without re-downloading it from your server."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendQuickReplies",
          "description": "`POST /instagram/messenger/sendQuickReplies` - up to **13 text chips**. They render in the Instagram **mobile app only** (invisible on instagram.com).",
          "item": [
            {
              "name": "Text chips",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"What are you looking for?\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Sizes\",\n      \"payload\": \"SIZES\"\n    },\n    {\n      \"title\": \"Shipping\",\n      \"payload\": \"SHIPPING\"\n    },\n    {\n      \"title\": \"Returns\",\n      \"payload\": \"RETURNS\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendQuickReplies",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendQuickReplies"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `body` | yes | <=1000 bytes |\n| `quickReplies` | yes | 1-13 items of `{title, payload}` -> else 8 |\n\n`title` is mandatory and <=20 chars; `payload` defaults to the title. **No `imageUrl`, no phone/email chips** on Instagram.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"What are you looking for?\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Sizes\",\n      \"payload\": \"SIZES\"\n    },\n    {\n      \"title\": \"Shipping\",\n      \"payload\": \"SHIPPING\"\n    },\n    {\n      \"title\": \"Returns\",\n      \"payload\": \"RETURNS\"\n    }\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendQuickReplies",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendQuickReplies"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `body` | yes | <=1000 bytes |\n| `quickReplies` | yes | 1-13 items of `{title, payload}` -> else 8 |\n\n`title` is mandatory and <=20 chars; `payload` defaults to the title. **No `imageUrl`, no phone/email chips** on Instagram.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"body\": \"What are you looking for?\"\n}"
                }
              ]
            },
            {
              "name": "Chips without payloads",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"body\": \"Should we call you back?\",\n  \"quickReplies\": [\n    {\n      \"title\": \"Yes please\"\n    },\n    {\n      \"title\": \"No thanks\"\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendQuickReplies",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendQuickReplies"
                  ]
                },
                "description": "With no `payload`, the chip title itself is what comes back on your incoming webhook."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendCarousel",
          "description": "`POST /instagram/messenger/sendCarousel` - generic template cards, IG-app rendering only.\n\nSame card structure as Facebook (folder 1) with two differences: buttons support **`url` and `postback` only** (a `call` button returns reason 8), and `aspectRatio` is not supported.\n\n> Media must be a **public https URL that Meta can download**. Replace the `{{sample_*_url}}` variables with your own files - the `example.com` defaults will be rejected by Meta (reason 15 / 18).",
          "item": [
            {
              "name": "One card with a postback button",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"cards\": [\n    {\n      \"title\": \"Summer sale\",\n      \"subtitle\": \"Up to 50% off\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"buttons\": [\n        {\n          \"type\": \"postback\",\n          \"title\": \"Show me\",\n          \"payload\": \"SHOW_SALE\"\n        }\n      ]\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendCarousel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendCarousel"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `cards` | yes | 1-10 cards -> else reason 8 |\n\nCard: `title` (mandatory, <=80), `subtitle` (<=80), `imageUrl`, `defaultUrl`, `buttons` (up to 3, `url`/`postback` only).\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"cards\": [\n    {\n      \"title\": \"Summer sale\",\n      \"subtitle\": \"Up to 50% off\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"buttons\": [\n        {\n          \"type\": \"postback\",\n          \"title\": \"Show me\",\n          \"payload\": \"SHOW_SALE\"\n        }\n      ]\n    }\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendCarousel",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendCarousel"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `cards` | yes | 1-10 cards -> else reason 8 |\n\nCard: `title` (mandatory, <=80), `subtitle` (<=80), `imageUrl`, `defaultUrl`, `buttons` (up to 3, `url`/`postback` only).\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"cards\": 1\n}"
                }
              ]
            },
            {
              "name": "Two cards with url buttons",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"cards\": [\n    {\n      \"title\": \"Running shoes\",\n      \"subtitle\": \"299 NIS\",\n      \"imageUrl\": \"{{sample_image_url}}\",\n      \"defaultUrl\": \"https://example.com/p/shoes\",\n      \"buttons\": [\n        {\n          \"type\": \"url\",\n          \"title\": \"Buy\",\n          \"url\": \"https://example.com/p/shoes\"\n        }\n      ]\n    },\n    {\n      \"title\": \"Sports socks\",\n      \"subtitle\": \"39 NIS\",\n      \"imageUrl\": \"{{sample_image_url_2}}\",\n      \"defaultUrl\": \"https://example.com/p/socks\",\n      \"buttons\": [\n        {\n          \"type\": \"url\",\n          \"title\": \"Buy\",\n          \"url\": \"https://example.com/p/socks\"\n        }\n      ]\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendCarousel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendCarousel"
                  ]
                },
                "description": "A product carousel. `defaultUrl` makes the whole card tappable."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendReaction",
          "description": "`POST /instagram/messenger/sendReaction` - react / unreact to a specific customer message. **Not written to history.**",
          "item": [
            {
              "name": "React with a heart",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"messageId\": \"{{ig_message_id}}\",\n  \"action\": \"react\",\n  \"reaction\": \"❤️\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendReaction",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendReaction"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `messageId` | yes | The IG message id from your incoming webhook -> missing -> 5 |\n| `action` | no (`react`) | `react` / `unreact` -> else 8 |\n| `reaction` | no (`love`) | `love` or an emoji (❤️ 😊 🎉) |\n\nSend again with a different emoji to change the reaction.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"messageId\": \"{{ig_message_id}}\",\n  \"action\": \"react\",\n  \"reaction\": \"❤️\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendReaction",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendReaction"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `messageId` | yes | The IG message id from your incoming webhook -> missing -> 5 |\n| `action` | no (`react`) | `react` / `unreact` -> else 8 |\n| `reaction` | no (`love`) | `love` or an emoji (❤️ 😊 🎉) |\n\nSend again with a different emoji to change the reaction.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"action\": \"react\"\n}"
                }
              ]
            },
            {
              "name": "React with a custom emoji",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"messageId\": \"{{ig_message_id}}\",\n  \"action\": \"react\",\n  \"reaction\": \"🎉\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendReaction",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendReaction"
                  ]
                },
                "description": "Any single emoji Instagram supports."
              },
              "response": []
            },
            {
              "name": "Remove the reaction",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"messageId\": \"{{ig_message_id}}\",\n  \"action\": \"unreact\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendReaction",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendReaction"
                  ]
                },
                "description": "`unreact` removes whatever reaction you put on that message. `reaction` is ignored here."
              },
              "response": []
            }
          ]
        },
        {
          "name": "sendMediaShare",
          "description": "`POST /instagram/messenger/sendMediaShare` - share one of **your own** IG posts inside the DM, rendered as a post card. Someone else's post cannot be shared.",
          "item": [
            {
              "name": "Share one of your posts",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"postId\": \"{{ig_media_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/sendMediaShare",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "sendMediaShare"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes | An IG media id **owned by this account** -> missing/invalid -> 5 |\n\nGet the id from `mediaId` of `/instagram/page/createPost`, or from `/instagram/page/getPosts`.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"postId\": \"{{ig_media_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/sendMediaShare",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "sendMediaShare"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes | An IG media id **owned by this account** -> missing/invalid -> 5 |\n\nGet the id from `mediaId` of `/instagram/page/createPost`, or from `/instagram/page/getPosts`.\n\n**Delivery: asynchronous.** You get `OK` + a `unique` id in ~1s; the real Meta message id arrives later as `meta_id` on your `sendStatus` webhook (see folder *5 - Webhooks*)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"postId\": \"17895695668004550\"\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "typing",
          "description": "`POST /instagram/messenger/typing` - sender actions. **Not written to history.**",
          "item": [
            {
              "name": "typing_on",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"action\": \"typing_on\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/typing",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "typing"
                  ]
                },
                "description": "`action`: `typing_on` (default) / `typing_off` / `mark_seen` -> else reason 8. Auto-expires after ~20s.\n\nFailures: 2, 3, 4, 6, 7, 8."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"action\": \"typing_on\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/messenger/typing",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "messenger",
                        "typing"
                      ]
                    },
                    "description": "`action`: `typing_on` (default) / `typing_off` / `mark_seen` -> else reason 8. Auto-expires after ~20s.\n\nFailures: 2, 3, 4, 6, 7, 8."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"timestamp\": 1783263291,\n  \"from\": \"{{from_ig_messenger}}\",\n  \"reason\": 1,\n  \"to\": \"17841400000000000\",\n  \"action\": \"typing_on\"\n}"
                }
              ]
            },
            {
              "name": "mark_seen",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_messenger}}\",\n  \"to\": \"{{igsid}}\",\n  \"action\": \"mark_seen\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/messenger/typing",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "messenger",
                    "typing"
                  ]
                },
                "description": "Marks the customer's last message as read."
              },
              "response": []
            }
          ]
        }
      ]
    },
    {
      "name": "3 - Facebook Page (type 3)",
      "description": "Requires a **`facebook_type: 3`** connection (`{{from_fb_page}}`).\n\n> ⚠️ This is the classic **reason 6** trap: a Messenger (type 1) connection cannot post. Publishing needs its own type-3 onboarding and its own `from`.\n\n**Every type-3 endpoint is synchronous**: the call goes straight to Meta and the response already carries the real `postId` / `commentId`. No `unique`, no queue, no webhook. A Meta rejection comes back as one of OUR reason codes 10-18 - never Meta's raw error text.\n\nIds returned here are the same ids `getPosts` / `getComments` return, and the same ids Meta uses - there is only one id space.",
      "item": [
        {
          "name": "createPost",
          "description": "`POST /facebook/page/createPost` - **one endpoint for every post kind**. Media always goes into the single `links` array; the kind is taken from `type`, or inferred from `links`:\n\n| `type` | Inferred when | `links` |\n|---|---|---|\n| `text` | `links` empty/omitted | none - `body` only |\n| `photo` | `links` given | 1 photo, or 2-10 for an album |\n| `video` | `links` is a single video URL | exactly 1 video |\n\nThere is **no separate link type** - put the URL inside `body` on a text post and Facebook builds the preview card itself.\n\n> Media must be a **public https URL that Meta can download**. Replace the `{{sample_*_url}}` variables with your own files - the `example.com` defaults will be rejected by Meta (reason 15 / 18).",
          "item": [
            {
              "name": "Text post",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"body\": \"We are open today until 18:00. Come say hi 👋\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `type` | no | `text` / `photo` / `video` -> else 8. Omit to infer |\n| `body` | for `text` | Post text / photo caption / video description. **Plain text, <=63,206 chars** (over -> 8). NO markdown or HTML - `*bold*`, `#`, `[x](y)` render literally. Emojis and `\\n` are fine |\n| `links` | for `photo`/`video` | Public https URLs (a single string is also accepted). Empty when required -> 5; a URL not starting `http` -> 5 |\n| `title` | no | Video title (video only) |\n| `scheduleTime` | no | UNIX seconds, **11 min - 30 days** ahead -> else 8. Omit/0 = publish now |\n\nFailures: 2, 3, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"body\": \"We are open today until 18:00. Come say hi 👋\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `type` | no | `text` / `photo` / `video` -> else 8. Omit to infer |\n| `body` | for `text` | Post text / photo caption / video description. **Plain text, <=63,206 chars** (over -> 8). NO markdown or HTML - `*bold*`, `#`, `[x](y)` render literally. Emojis and `\\n` are fine |\n| `links` | for `photo`/`video` | Public https URLs (a single string is also accepted). Empty when required -> 5; a URL not starting `http` -> 5 |\n| `title` | no | Video title (video only) |\n| `scheduleTime` | no | UNIX seconds, **11 min - 30 days** ahead -> else 8. Omit/0 = publish now |\n\nFailures: 2, 3, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"timestamp\": 1783506353,\n  \"reason\": 1,\n  \"type\": \"text\",\n  \"body\": \"We are open today until 18:00. Come say hi 👋\",\n  \"postId\": \"119324881085321_122093459712345\"\n}"
                }
              ]
            },
            {
              "name": "Text post with a link preview",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"body\": \"Our new collection is live 🎉 https://example.com/summer\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "No `link` field exists - just include the URL inside `body`. Facebook fetches the page and attaches the preview card automatically (make sure the target page has OpenGraph tags)."
              },
              "response": []
            },
            {
              "name": "Single photo",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"body\": \"Fresh out of the oven 🥐\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "`type` is inferred as `photo`. `body` becomes the caption. The response echoes `type` and `photos` (count)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"body\": \"Fresh out of the oven 🥐\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "`type` is inferred as `photo`. `body` becomes the caption. The response echoes `type` and `photos` (count)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"timestamp\": 1783506353,\n  \"reason\": 1,\n  \"type\": \"photo\",\n  \"photos\": 1,\n  \"body\": \"Fresh out of the oven 🥐\",\n  \"postId\": \"119324881085321_122093459712345\"\n}"
                }
              ]
            },
            {
              "name": "Photo album (2-10 photos)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\",\n    \"{{sample_image_url_2}}\"\n  ],\n  \"body\": \"This week at the shop 📸\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "2-10 links -> one album post with a shared caption (each photo is uploaded unpublished, then one feed post ties them together). More than 10 -> reason 8. Photos and videos **cannot be mixed**."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\",\n    \"{{sample_image_url_2}}\"\n  ],\n  \"body\": \"This week at the shop 📸\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "2-10 links -> one album post with a shared caption (each photo is uploaded unpublished, then one feed post ties them together). More than 10 -> reason 8. Photos and videos **cannot be mixed**."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"timestamp\": 1783506353,\n  \"reason\": 1,\n  \"type\": \"photo\",\n  \"photos\": 2,\n  \"body\": \"This week at the shop 📸\",\n  \"postId\": \"119324881085321_122093459712345\"\n}"
                }
              ]
            },
            {
              "name": "Video",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_video_url}}\"\n  ],\n  \"body\": \"Behind the scenes of today's shoot.\",\n  \"title\": \"Behind the scenes\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "Exactly **one** video link (mp4/mov/webm/avi/3gp/mkv) - 2 or more -> reason 8. `body` is the description, `title` the video title. Keep the file under ~1GB."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_video_url}}\"\n  ],\n  \"body\": \"Behind the scenes of today's shoot.\",\n  \"title\": \"Behind the scenes\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "Exactly **one** video link (mp4/mov/webm/avi/3gp/mkv) - 2 or more -> reason 8. `body` is the description, `title` the video title. Keep the file under ~1GB."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"timestamp\": 1783506353,\n  \"reason\": 1,\n  \"type\": \"video\",\n  \"body\": \"Behind the scenes of today's shoot.\",\n  \"postId\": \"119324881085321_122093459712345\"\n}"
                }
              ]
            },
            {
              "name": "Scheduled text post (1 hour from now)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"body\": \"Doors open at 09:00 tomorrow ⏰\",\n  \"scheduleTime\": \"{{schedule_time}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "Native Facebook scheduling, **11 minutes to 30 days** ahead - anything outside that window returns reason 8.\n\nThe pre-request script of this sample sets `{{schedule_time}}` to *now + 1 hour*, so you can just hit Send. A plain integer is equally fine - it is quoted here only so the Postman variable substitutes cleanly.\n\nThe `postId` is returned immediately; the post goes live at `scheduleTime` and until then `getPosts` shows it with `is_published: false`."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"body\": \"Doors open at 09:00 tomorrow ⏰\",\n  \"scheduleTime\": \"{{schedule_time}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "Native Facebook scheduling, **11 minutes to 30 days** ahead - anything outside that window returns reason 8.\n\nThe pre-request script of this sample sets `{{schedule_time}}` to *now + 1 hour*, so you can just hit Send. A plain integer is equally fine - it is quoted here only so the Postman variable substitutes cleanly.\n\nThe `postId` is returned immediately; the post goes live at `scheduleTime` and until then `getPosts` shows it with `is_published: false`."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"timestamp\": 1783506353,\n  \"reason\": 1,\n  \"type\": \"text\",\n  \"body\": \"Doors open at 09:00 tomorrow ⏰\",\n  \"scheduleTime\": 1786000000,\n  \"postId\": \"119324881085321_122093459712345\"\n}"
                }
              ],
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "// scheduleTime must be 11 minutes - 30 days ahead (else reason 8).",
                      "// Here we simply set it to 1 hour from now.",
                      "pm.collectionVariables.set('schedule_time', Math.floor(Date.now() / 1000) + 3600);"
                    ]
                  }
                }
              ]
            },
            {
              "name": "Scheduled photo post (1 hour from now)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"body\": \"Tomorrow's special 🍝\",\n  \"scheduleTime\": \"{{schedule_time}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createPost"
                  ]
                },
                "description": "Any kind can be scheduled - text, photo, album or video."
              },
              "response": [],
              "event": [
                {
                  "listen": "prerequest",
                  "script": {
                    "type": "text/javascript",
                    "exec": [
                      "// scheduleTime must be 11 minutes - 30 days ahead (else reason 8).",
                      "// Here we simply set it to 1 hour from now.",
                      "pm.collectionVariables.set('schedule_time', Math.floor(Date.now() / 1000) + 3600);"
                    ]
                  }
                }
              ]
            }
          ]
        },
        {
          "name": "editPost",
          "description": "`POST /facebook/page/editPost` - edit the **text only**. Media and link cards cannot be changed after publishing (Meta restriction) - delete and re-create instead.",
          "item": [
            {
              "name": "Edit the post text",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"body\": \"Updated: we are open until 20:00 today.\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/editPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "editPost"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes | -> else reason 4 |\n| `body` | yes | New text, plain text <=63,206 chars. Missing -> 5, over -> 8 |\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"body\": \"Updated: we are open until 20:00 today.\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/editPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "editPost"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes | -> else reason 4 |\n| `body` | yes | New text, plain text <=63,206 chars. Missing -> 5, over -> 8 |\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"119324881085321_122093459712345\",\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "deletePost",
          "description": "`POST /facebook/page/deletePost` - permanent.",
          "item": [
            {
              "name": "Delete a post",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/deletePost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "deletePost"
                  ]
                },
                "description": "`postId` mandatory -> else reason 4. Cannot be undone.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/deletePost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "deletePost"
                      ]
                    },
                    "description": "`postId` mandatory -> else reason 4. Cannot be undone.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"119324881085321_122093459712345\",\n  \"deleted\": true,\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "createComment",
          "description": "`POST /facebook/page/createComment` - comment **as the Page**, either on a post (top-level) or on a comment (reply).",
          "item": [
            {
              "name": "Comment on a post",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"body\": \"Thanks everyone for the kind words! 🙏\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createComment"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes (or `commentId`) | Comment on a post. Neither valid -> 4 |\n| `commentId` | yes (or `postId`) | Reply to a comment. **If both are sent, `commentId` wins** |\n| `body` | yes (or media) | Plain text <=8,000 chars. No body AND no media -> 5; over 8,000 -> 8 |\n| `url` | no | External image to attach - must start `http` else 5 |\n| `attachmentId` | no | Reusable attachment instead of `url` (ignored when `url` is given) |\n\nThe response carries the real new `commentId` - use it to reply again, hide, delete, like or private-reply.\n\nFailures: 2, 3, 4, 5, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"body\": \"Thanks everyone for the kind words! 🙏\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/createComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "createComment"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes (or `commentId`) | Comment on a post. Neither valid -> 4 |\n| `commentId` | yes (or `postId`) | Reply to a comment. **If both are sent, `commentId` wins** |\n| `body` | yes (or media) | Plain text <=8,000 chars. No body AND no media -> 5; over 8,000 -> 8 |\n| `url` | no | External image to attach - must start `http` else 5 |\n| `attachmentId` | no | Reusable attachment instead of `url` (ignored when `url` is given) |\n\nThe response carries the real new `commentId` - use it to reply again, hide, delete, like or private-reply.\n\nFailures: 2, 3, 4, 5, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"target\": \"119324881085321_122093459712345\",\n  \"commentId\": \"122093459712345_98765432109876\",\n  \"body\": \"Thanks everyone for the kind words! 🙏\",\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Reply to a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"body\": \"Sent you the details, check your inbox 📩\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createComment"
                  ]
                },
                "description": "Send `commentId` instead of `postId` to answer one specific person.\n\n> Replying to a reply is not possible - Facebook allows a single nesting level, so reply to the parent comment instead."
              },
              "response": []
            },
            {
              "name": "Comment with an image",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"body\": \"Here is the size chart 👇\",\n  \"url\": \"{{sample_image_url}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createComment"
                  ]
                },
                "description": "`url` attaches one external image to the comment. A URL that does not start with `http` returns reason 5."
              },
              "response": []
            },
            {
              "name": "Comment with a reusable attachment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"body\": \"Our price list:\",\n  \"attachmentId\": \"{{fb_attachment_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/createComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "createComment"
                  ]
                },
                "description": "Use `attachmentId` to attach media you already uploaded. Ignored if `url` is also present."
              },
              "response": []
            }
          ]
        },
        {
          "name": "hideComment",
          "description": "`POST /facebook/page/hideComment` - hide / unhide. A hidden comment stays visible to its writer and their friends, so they never know - the softest moderation tool.",
          "item": [
            {
              "name": "Hide a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"hide\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/hideComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "hideComment"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `hide` | no (1) | `1` = hide, `0` = unhide |\n\nReversible, unlike deleteComment.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"hide\": 1\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/hideComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "hideComment"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `hide` | no (1) | `1` = hide, `0` = unhide |\n\nReversible, unlike deleteComment.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"122093459712345_98765432109876\",\n  \"hidden\": true,\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Unhide a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"hide\": 0\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/hideComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "hideComment"
                  ]
                },
                "description": "`hide: 0` brings the comment back into public view."
              },
              "response": []
            }
          ]
        },
        {
          "name": "deleteComment",
          "description": "`POST /facebook/page/deleteComment` - permanent removal (hideComment is the reversible option).",
          "item": [
            {
              "name": "Delete a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/deleteComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "deleteComment"
                  ]
                },
                "description": "`commentId` mandatory -> else reason 4.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/deleteComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "deleteComment"
                      ]
                    },
                    "description": "`commentId` mandatory -> else reason 4.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"122093459712345_98765432109876\",\n  \"deleted\": true,\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "likeComment",
          "description": "`POST /facebook/page/likeComment` - like / unlike as the Page. **Facebook only** - Instagram has no comment-liking API.\n\nOnly a plain **LIKE** is possible: Meta does not allow publishing typed reactions (LOVE / WOW / HAHA / SAD / ANGRY / CARE) through the API - the reactions edge is read-only - so there is no reaction-type option.",
          "item": [
            {
              "name": "Like a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"like\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/likeComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "likeComment"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `like` | no (1) | `1` = like, `0` = unlike |\n\nLiking an already-liked comment returns reason 18.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"like\": 1\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/likeComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "likeComment"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `like` | no (1) | `1` = like, `0` = unlike |\n\nLiking an already-liked comment returns reason 18.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"122093459712345_98765432109876\",\n  \"like\": true,\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Unlike a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"like\": 0\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/likeComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "likeComment"
                  ]
                },
                "description": "Removes the Page's like."
              },
              "response": []
            }
          ]
        },
        {
          "name": "privateReply",
          "description": "`POST /facebook/page/privateReply` - send a **one-time private DM** to the author of a public comment, or to the author of a **visitor post** on your Page.\n\nMeta's rules: **one** private reply per comment/post, within **7 days** of it. The DM does not open a conversation window - if the user answers, a normal 24h Messenger window opens.",
          "item": [
            {
              "name": "DM the author of a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"body\": \"Hi! Sending you the details here in private 📩\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/privateReply",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "privateReply"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes (or `postId`) | DMs the comment's author. **If both are sent, `commentId` wins** |\n| `postId` | yes (or `commentId`) | DMs the author of a **visitor post** on your Page - not one of your own posts |\n| `body` | yes | <=2000 chars. Missing -> 5, over -> 8 |\n\nA second reply to the same comment returns **reason 13**.\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\",\n  \"body\": \"Hi! Sending you the details here in private 📩\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/privateReply",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "privateReply"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes (or `postId`) | DMs the comment's author. **If both are sent, `commentId` wins** |\n| `postId` | yes (or `commentId`) | DMs the author of a **visitor post** on your Page - not one of your own posts |\n| `body` | yes | <=2000 chars. Missing -> 5, over -> 8 |\n\nA second reply to the same comment returns **reason 13**.\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"target\": \"122093459712345_98765432109876\",\n  \"messageId\": \"m_AbCdEfGhIjKlMnOpQrStUv\",\n  \"body\": \"Hi! Sending you the details here in private 📩\",\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "DM the author of a visitor post",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_visitor_post_id}}\",\n  \"body\": \"Thanks for posting on our Page - here are the details 📩\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/privateReply",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "privateReply"
                  ]
                },
                "description": "A **visitor post** is a post a customer published on your Page's timeline. You cannot private-reply to your own posts (there is no single recipient) - that returns a Meta rejection.\n\nFill the `fb_visitor_post_id` variable first."
              },
              "response": []
            }
          ]
        },
        {
          "name": "getLead",
          "description": "`POST /facebook/page/getLead` - fetch the content of a Lead Ads lead.\n\nMeta's `leadgen` webhook carries only a `leadgen_id`; this endpoint returns the actual answers. Requires the `leads_retrieval` permission on the connection.",
          "item": [
            {
              "name": "Get a lead",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"leadgenId\": \"{{leadgen_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getLead",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getLead"
                  ]
                },
                "description": "`leadgenId` mandatory -> else reason 4. The data comes back in the same response - no webhook.\n\nFailures: 2, 3, 4, 6, 7, 10-18 (11 = the `leads_retrieval` permission is missing).\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"leadgenId\": \"{{leadgen_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/getLead",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "getLead"
                      ]
                    },
                    "description": "`leadgenId` mandatory -> else reason 4. The data comes back in the same response - no webhook.\n\nFailures: 2, 3, 4, 6, 7, 10-18 (11 = the `leads_retrieval` permission is missing).\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"leadgenId\": \"444444444444444\",\n  \"lead\": {\n    \"id\": \"444444444444444\",\n    \"created_time\": \"2026-07-06T08:30:00+0000\",\n    \"ad_id\": \"1234\",\n    \"form_id\": \"5678\",\n    \"is_organic\": false,\n    \"field_data\": [\n      {\n        \"name\": \"full_name\",\n        \"values\": [\n          \"Israel Israeli\"\n        ]\n      },\n      {\n        \"name\": \"email\",\n        \"values\": [\n          \"israel@example.com\"\n        ]\n      },\n      {\n        \"name\": \"phone_number\",\n        \"values\": [\n          \"+972500000000\"\n        ]\n      }\n    ]\n  },\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "getPosts",
          "description": "`POST /facebook/page/getPosts` - list the Page's posts (published **and** still-scheduled) or fetch one post.\n\nPermissions: `pages_read_engagement` (+ `pages_manage_posts` to include scheduled posts).",
          "item": [
            {
              "name": "List posts",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"limit\": 25\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `limit` | no (25) | 1-100 -> else reason 8 |\n| `after` | no | Paging cursor from the previous response |\n| `postId` | no | Fetch ONE post instead of a list (returns `post`). Invalid -> 4 |\n\n**Post fields** - `id` (`<page_id>_<post_id>`), `message` (empty for media-only posts), `created_time` / `updated_time` (**UNIX UTC seconds**, int), `permalink_url`, `full_picture`, `is_published`, `scheduled_publish_time` (only on a still-scheduled post), `shares`, `total_comments`, `total_reactions`, `attachments`, `story`.\n\nScheduled posts (`is_published: false`) are listed first - there are only a handful; the cursor pages through the published ones.\n\n**Paging:** while `paging.hasNext` is `true`, resend the same request with `\"after\": \"<paging.after>\"`. This collection stores the cursor in `{{after_cursor}}` for you.\n\n> Visitor posts (posts other people published on the Page) are not exposed here - ask us if you need them.\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"limit\": 25\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/getPosts",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "getPosts"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `limit` | no (25) | 1-100 -> else reason 8 |\n| `after` | no | Paging cursor from the previous response |\n| `postId` | no | Fetch ONE post instead of a list (returns `post`). Invalid -> 4 |\n\n**Post fields** - `id` (`<page_id>_<post_id>`), `message` (empty for media-only posts), `created_time` / `updated_time` (**UNIX UTC seconds**, int), `permalink_url`, `full_picture`, `is_published`, `scheduled_publish_time` (only on a still-scheduled post), `shares`, `total_comments`, `total_reactions`, `attachments`, `story`.\n\nScheduled posts (`is_published: false`) are listed first - there are only a handful; the cursor pages through the published ones.\n\n**Paging:** while `paging.hasNext` is `true`, resend the same request with `\"after\": \"<paging.after>\"`. This collection stores the cursor in `{{after_cursor}}` for you.\n\n> Visitor posts (posts other people published on the Page) are not exposed here - ask us if you need them.\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"count\": 2,\n  \"posts\": [\n    {\n      \"id\": \"119324881085321_122093459712345\",\n      \"message\": \"Hello fans!\",\n      \"created_time\": 1783596120,\n      \"updated_time\": 1783603417,\n      \"permalink_url\": \"https://www.facebook.com/...\",\n      \"full_picture\": \"https://scontent...\",\n      \"is_published\": true,\n      \"shares\": 3,\n      \"total_comments\": 12,\n      \"total_reactions\": 41,\n      \"attachments\": {\n        \"data\": [\n          {\n            \"media_type\": \"photo\",\n            \"url\": \"https://...\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"119324881085321_555555555555555\",\n      \"message\": \"Going live next week!\",\n      \"created_time\": 1783600000,\n      \"updated_time\": 1783600000,\n      \"is_published\": false,\n      \"scheduled_publish_time\": 1786000000,\n      \"shares\": 0,\n      \"total_comments\": 0,\n      \"total_reactions\": 0\n    }\n  ],\n  \"paging\": {\n    \"after\": \"QVFIU...\",\n    \"hasNext\": true\n  },\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "List posts - next page",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"limit\": 25,\n  \"after\": \"{{after_cursor}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "Same request plus `after`. `{{after_cursor}}` is filled automatically from the previous list response, so you can keep pressing Send until `paging.hasNext` is `false`."
              },
              "response": []
            },
            {
              "name": "Get one post",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "With `postId` the response has a single `post` object instead of the `posts` array (and no `paging`)."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/getPosts",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "getPosts"
                      ]
                    },
                    "description": "With `postId` the response has a single `post` object instead of the `posts` array (and no `paging`)."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"post\": {\n    \"id\": \"119324881085321_122093459712345\",\n    \"message\": \"Hello fans!\",\n    \"created_time\": 1783596120,\n    \"updated_time\": 1783603417,\n    \"permalink_url\": \"https://www.facebook.com/...\",\n    \"is_published\": true,\n    \"shares\": 3,\n    \"total_comments\": 12,\n    \"total_reactions\": 41\n  },\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Highest limit (100)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"limit\": 100\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "100 is the maximum - `limit: 101` or `limit: 0` returns reason 8."
              },
              "response": []
            }
          ]
        },
        {
          "name": "getComments",
          "description": "`POST /facebook/page/getComments` - all comments of a post, or the replies of one comment.",
          "item": [
            {
              "name": "Comments of a post",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"limit\": 25\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getComments"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes (or `commentId`) | Comments of a post. **If both are sent, `commentId` wins** |\n| `commentId` | yes (or `postId`) | Replies of one comment |\n| `limit` | no (25) | 1-100 -> else 8 |\n| `after` | no | Paging cursor |\n| `order` | no (`chronological`) | `chronological` / `reverse_chronological` -> else 8 |\n| `filter` | no (`toplevel`) | `toplevel` = top-level comments only / `stream` = replies included, flat -> else 8 |\n\n**Comment fields** - `id`, `message`, `from` (may be absent for non-page users, privacy), `created_time` (**UNIX UTC seconds**, int), `like_count`, `comment_count` (number of replies), `is_hidden`, `parent.id` (on replies), `attachment`, `permalink_url`.\n\nThe `id`s plug straight into hideComment / deleteComment / likeComment / privateReply / createComment(reply).\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"limit\": 25\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/facebook/page/getComments",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "facebook",
                        "page",
                        "getComments"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `postId` | yes (or `commentId`) | Comments of a post. **If both are sent, `commentId` wins** |\n| `commentId` | yes (or `postId`) | Replies of one comment |\n| `limit` | no (25) | 1-100 -> else 8 |\n| `after` | no | Paging cursor |\n| `order` | no (`chronological`) | `chronological` / `reverse_chronological` -> else 8 |\n| `filter` | no (`toplevel`) | `toplevel` = top-level comments only / `stream` = replies included, flat -> else 8 |\n\n**Comment fields** - `id`, `message`, `from` (may be absent for non-page users, privacy), `created_time` (**UNIX UTC seconds**, int), `like_count`, `comment_count` (number of replies), `is_hidden`, `parent.id` (on replies), `attachment`, `permalink_url`.\n\nThe `id`s plug straight into hideComment / deleteComment / likeComment / privateReply / createComment(reply).\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_fb_page}}\",\n  \"target\": \"119324881085321_122093459712345\",\n  \"count\": 2,\n  \"comments\": [\n    {\n      \"id\": \"122093459712345_98765432109876\",\n      \"message\": \"Nice post!\",\n      \"from\": {\n        \"id\": \"1234567890\",\n        \"name\": \"Israel Israeli\",\n        \"picture\": {\n          \"data\": {\n            \"url\": \"https://...\"\n          }\n        }\n      },\n      \"created_time\": 1783591200,\n      \"like_count\": 2,\n      \"comment_count\": 1,\n      \"is_hidden\": false,\n      \"permalink_url\": \"https://www.facebook.com/...\"\n    },\n    {\n      \"id\": \"122093459712345_11111111111111\",\n      \"message\": \"Do you ship to Haifa?\",\n      \"created_time\": 1783592000,\n      \"like_count\": 0,\n      \"comment_count\": 0,\n      \"is_hidden\": false,\n      \"permalink_url\": \"https://www.facebook.com/...\"\n    }\n  ],\n  \"paging\": {\n    \"after\": \"QVFIU...\",\n    \"hasNext\": false\n  },\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Newest comments first",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"order\": \"reverse_chronological\",\n  \"limit\": 25\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getComments"
                  ]
                },
                "description": "`reverse_chronological` = newest first - what a moderation queue usually wants."
              },
              "response": []
            },
            {
              "name": "Replies of one comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"commentId\": \"{{fb_comment_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getComments"
                  ]
                },
                "description": "Send `commentId` to read the replies of that comment instead of the post's comments."
              },
              "response": []
            },
            {
              "name": "Flat stream (comments + replies)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"filter\": \"stream\",\n  \"limit\": 50\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getComments"
                  ]
                },
                "description": "`filter: stream` returns replies inline with the top-level comments as one flat list (each reply carries `parent.id`). `toplevel` (the default) returns only top-level comments."
              },
              "response": []
            },
            {
              "name": "Comments - next page",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_fb_page}}\",\n  \"postId\": \"{{fb_post_id}}\",\n  \"limit\": 25,\n  \"after\": \"{{after_cursor}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/facebook/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "facebook",
                    "page",
                    "getComments"
                  ]
                },
                "description": "Keep sending while `paging.hasNext` is `true`."
              },
              "response": []
            }
          ]
        }
      ]
    },
    {
      "name": "4 - Instagram Page (type 4)",
      "description": "Requires a **`facebook_type: 4`** connection (`{{from_ig_page}}`).\n\n**Every type-4 endpoint is synchronous**: the response already carries the real `mediaId` / `commentId`. No `unique`, no queue, no webhook. A Meta rejection comes back as one of OUR reason codes 10-18.\n\n**Global Instagram publishing rules**\n\n- All media must be **public HTTPS URLs** - Meta downloads them. No binary upload.\n- Images: **JPEG only**, <=8MB, aspect ratio between 4:5 and 1.91:1, width 320-1440px. A PNG is rejected with reason 15.\n- **100 API-published posts per rolling 24 hours** per account (a carousel counts as 1). Over it -> **reason 16**.\n- **No native scheduling** - `scheduleTime` does not exist here. Hold the call on your side and send it at the moment you want to publish.\n- Published media **cannot be edited** - no caption edit, no media swap. The only post-publish change is `toggleComments`. Delete and re-post to change content.\n- Video / reel / carousel publishing takes time: we create the container and poll Meta inline (every 5s, up to ~90s), then publish and return the real media id in the SAME response. If Meta has not finished in time you get **reason 17** - nothing was published, just retry the identical request in ~1 minute.\n\n> Media must be a **public https URL that Meta can download**. Replace the `{{sample_*_url}}` variables with your own files - the `example.com` defaults will be rejected by Meta (reason 15 / 18).",
      "item": [
        {
          "name": "createPost",
          "description": "`POST /instagram/page/createPost` - **one endpoint for every media kind**. Media always goes into the single `links` array (each item's image/video type is inferred from its extension); the kind is taken from `mediaType`, or inferred:\n\n| `mediaType` | Inferred when | `links` |\n|---|---|---|\n| `image` | 1 link, non-video extension (default) | exactly 1 |\n| `reel` (alias `video`) | 1 link, video extension | exactly 1 |\n| `story` | **never inferred** - must be explicit | exactly 1 |\n| `carousel` | 2+ links | 2-10 |\n",
          "item": [
            {
              "name": "Image",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"caption\": \"New arrivals just landed 🛍️ #newin #tlv\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaType` | no | `image` / `reel` / `video` (=reel) / `story` / `carousel` -> else 8 |\n| `links` | yes | Public https URLs (a single string is also accepted). Empty -> 5; a URL not starting `http` -> 5. image/reel/story: exactly 1 item (more -> 8); carousel: 2-10 (else 8) |\n| `caption` | no | **Plain text <=2,200 chars** (over -> 8), up to 30 #hashtags and 20 @mentions. No markdown/HTML. **Stories ignore captions** |\n| `altText` | no | Accessibility text <=1000 chars -> else 8. **Image posts only** |\n| `coverUrl` | no | Reel cover image, https -> else 5. **Reels only** |\n| `shareToFeed` | no | Reels: `1` = also show in the feed grid, `0` = Reels tab only |\n\nSingle posts echo `url`; a carousel echoes `items` (count).\n\nFailures: 2, 3, 5, 6, 7, 8, **15** (bad format - remember JPEG only), **16** (daily limit), **17** (still processing - retry), 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"caption\": \"New arrivals just landed 🛍️ #newin #tlv\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaType` | no | `image` / `reel` / `video` (=reel) / `story` / `carousel` -> else 8 |\n| `links` | yes | Public https URLs (a single string is also accepted). Empty -> 5; a URL not starting `http` -> 5. image/reel/story: exactly 1 item (more -> 8); carousel: 2-10 (else 8) |\n| `caption` | no | **Plain text <=2,200 chars** (over -> 8), up to 30 #hashtags and 20 @mentions. No markdown/HTML. **Stories ignore captions** |\n| `altText` | no | Accessibility text <=1000 chars -> else 8. **Image posts only** |\n| `coverUrl` | no | Reel cover image, https -> else 5. **Reels only** |\n| `shareToFeed` | no | Reels: `1` = also show in the feed grid, `0` = Reels tab only |\n\nSingle posts echo `url`; a carousel echoes `items` (count).\n\nFailures: 2, 3, 5, 6, 7, 8, **15** (bad format - remember JPEG only), **16** (daily limit), **17** (still processing - retry), 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"timestamp\": 1783263291,\n  \"reason\": 1,\n  \"mediaType\": \"image\",\n  \"url\": \"https://example.com/photo.jpg\",\n  \"caption\": \"New arrivals just landed 🛍️ #newin #tlv\",\n  \"mediaId\": \"17895695668004550\"\n}"
                },
                {
                  "name": "Failure - still processing (retry the same request)",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"caption\": \"New arrivals just landed 🛍️ #newin #tlv\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaType` | no | `image` / `reel` / `video` (=reel) / `story` / `carousel` -> else 8 |\n| `links` | yes | Public https URLs (a single string is also accepted). Empty -> 5; a URL not starting `http` -> 5. image/reel/story: exactly 1 item (more -> 8); carousel: 2-10 (else 8) |\n| `caption` | no | **Plain text <=2,200 chars** (over -> 8), up to 30 #hashtags and 20 @mentions. No markdown/HTML. **Stories ignore captions** |\n| `altText` | no | Accessibility text <=1000 chars -> else 8. **Image posts only** |\n| `coverUrl` | no | Reel cover image, https -> else 5. **Reels only** |\n| `shareToFeed` | no | Reels: `1` = also show in the feed grid, `0` = Reels tab only |\n\nSingle posts echo `url`; a carousel echoes `items` (count).\n\nFailures: 2, 3, 5, 6, 7, 8, **15** (bad format - remember JPEG only), **16** (daily limit), **17** (still processing - retry), 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"FAIL\",\n  \"reason\": 17\n}"
                },
                {
                  "name": "Failure - daily publish limit (100 / 24h)",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"caption\": \"New arrivals just landed 🛍️ #newin #tlv\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaType` | no | `image` / `reel` / `video` (=reel) / `story` / `carousel` -> else 8 |\n| `links` | yes | Public https URLs (a single string is also accepted). Empty -> 5; a URL not starting `http` -> 5. image/reel/story: exactly 1 item (more -> 8); carousel: 2-10 (else 8) |\n| `caption` | no | **Plain text <=2,200 chars** (over -> 8), up to 30 #hashtags and 20 @mentions. No markdown/HTML. **Stories ignore captions** |\n| `altText` | no | Accessibility text <=1000 chars -> else 8. **Image posts only** |\n| `coverUrl` | no | Reel cover image, https -> else 5. **Reels only** |\n| `shareToFeed` | no | Reels: `1` = also show in the feed grid, `0` = Reels tab only |\n\nSingle posts echo `url`; a carousel echoes `items` (count).\n\nFailures: 2, 3, 5, 6, 7, 8, **15** (bad format - remember JPEG only), **16** (daily limit), **17** (still processing - retry), 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"FAIL\",\n  \"reason\": 16\n}"
                }
              ]
            },
            {
              "name": "Image with alt text (accessibility)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"image\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ],\n  \"caption\": \"Our bestseller is back in stock ✨\",\n  \"altText\": \"A pair of red running shoes on a wooden table\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "`altText` is read by screen readers. Image posts only - sending it with a reel/story/carousel is ignored, and over 1000 chars returns reason 8."
              },
              "response": []
            },
            {
              "name": "Reel (video)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"reel\",\n  \"links\": [\n    \"{{sample_video_url}}\"\n  ],\n  \"caption\": \"Watch how we make it 🎬 #behindthescenes\",\n  \"coverUrl\": \"{{sample_cover_url}}\",\n  \"shareToFeed\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "**Any single-video post on Instagram is a reel** - that is Meta's rule, there is no plain video post any more. `video` is accepted as an alias.\n\n- Reels-tab eligible: **5-90 seconds, 9:16 portrait**. Other sizes still publish, just as a regular video post.\n- `coverUrl` sets the thumbnail; `shareToFeed: 1` also puts it in the profile grid.\n- This call **blocks while Meta processes the video** (polling up to ~90s) and then returns the real `mediaId`. On reason 17 nothing was published - retry the identical request."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"reel\",\n  \"links\": [\n    \"{{sample_video_url}}\"\n  ],\n  \"caption\": \"Watch how we make it 🎬 #behindthescenes\",\n  \"coverUrl\": \"{{sample_cover_url}}\",\n  \"shareToFeed\": 1\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "**Any single-video post on Instagram is a reel** - that is Meta's rule, there is no plain video post any more. `video` is accepted as an alias.\n\n- Reels-tab eligible: **5-90 seconds, 9:16 portrait**. Other sizes still publish, just as a regular video post.\n- `coverUrl` sets the thumbnail; `shareToFeed: 1` also puts it in the profile grid.\n- This call **blocks while Meta processes the video** (polling up to ~90s) and then returns the real `mediaId`. On reason 17 nothing was published - retry the identical request."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"timestamp\": 1783263291,\n  \"reason\": 1,\n  \"mediaType\": \"reel\",\n  \"url\": \"https://example.com/video.mp4\",\n  \"caption\": \"Watch how we make it 🎬 #behindthescenes\",\n  \"mediaId\": \"17895695668004550\"\n}"
                }
              ]
            },
            {
              "name": "Reel - Reels tab only (not in the grid)",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"reel\",\n  \"links\": [\n    \"{{sample_video_url}}\"\n  ],\n  \"caption\": \"Quick tip of the day 💡\",\n  \"shareToFeed\": 0\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "`shareToFeed: 0` keeps the reel out of the profile grid - it lives in the Reels tab and the feed of followers only."
              },
              "response": []
            },
            {
              "name": "Story - image",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"story\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "`mediaType: story` is **never inferred** - you must say it explicitly.\n\n- Exactly 1 image or video.\n- Lives 24 hours, then disappears (it still shows in `getPosts` with `type: \"stories\"` while live).\n- **Captions are ignored** on stories, and stickers / polls / link stickers are not available through the API."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"story\",\n  \"links\": [\n    \"{{sample_image_url}}\"\n  ]\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "`mediaType: story` is **never inferred** - you must say it explicitly.\n\n- Exactly 1 image or video.\n- Lives 24 hours, then disappears (it still shows in `getPosts` with `type: \"stories\"` while live).\n- **Captions are ignored** on stories, and stickers / polls / link stickers are not available through the API."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"timestamp\": 1783263291,\n  \"reason\": 1,\n  \"mediaType\": \"story\",\n  \"url\": \"https://example.com/photo.jpg\",\n  \"mediaId\": \"17895695668004550\"\n}"
                }
              ]
            },
            {
              "name": "Story - video",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"story\",\n  \"links\": [\n    \"{{sample_video_url}}\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "Same call with a video link. Keep it **<=60 seconds**. Like every video this one is processed by Meta first, so the call may take a few seconds (reason 17 = retry)."
              },
              "response": []
            },
            {
              "name": "Carousel - 2 images",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\",\n    \"{{sample_image_url_2}}\"\n  ],\n  \"caption\": \"Swipe to see both colours ➡️\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "2+ links are inferred as a `carousel` (2-10 items, else reason 8). The caption sits on the whole carousel, and the response echoes `items` instead of `url`.\n\n> An individual carousel child **cannot** be deleted later - only the whole carousel."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"links\": [\n    \"{{sample_image_url}}\",\n    \"{{sample_image_url_2}}\"\n  ],\n  \"caption\": \"Swipe to see both colours ➡️\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createPost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createPost"
                      ]
                    },
                    "description": "2+ links are inferred as a `carousel` (2-10 items, else reason 8). The caption sits on the whole carousel, and the response echoes `items` instead of `url`.\n\n> An individual carousel child **cannot** be deleted later - only the whole carousel."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"timestamp\": 1783263291,\n  \"reason\": 1,\n  \"mediaType\": \"carousel\",\n  \"items\": 2,\n  \"caption\": \"Swipe to see both colours ➡️\",\n  \"mediaId\": \"17895695668004550\"\n}"
                }
              ]
            },
            {
              "name": "Carousel - image + video mixed",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaType\": \"carousel\",\n  \"links\": [\n    \"{{sample_image_url}}\",\n    \"{{sample_video_url}}\",\n    \"{{sample_image_url_2}}\"\n  ],\n  \"caption\": \"The full story of today's launch 📸🎬\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createPost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createPost"
                  ]
                },
                "description": "Images and videos can be mixed inside one carousel - each item's type is inferred from its extension. Videos make the call slower (Meta processes every child before publishing)."
              },
              "response": []
            }
          ]
        },
        {
          "name": "toggleComments",
          "description": "`POST /instagram/page/toggleComments` - enable/disable comments on a media object. **The only post-publish edit Instagram allows.**",
          "item": [
            {
              "name": "Disable comments",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"enabled\": 0\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/toggleComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "toggleComments"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaId` | yes | -> else reason 4 |\n| `enabled` | no (1) | `1` = comments on, `0` = comments off |\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"enabled\": 0\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/toggleComments",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "toggleComments"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaId` | yes | -> else reason 4 |\n| `enabled` | no (1) | `1` = comments on, `0` = comments off |\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"17895695668004550\",\n  \"enabled\": false,\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Enable comments",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"enabled\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/toggleComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "toggleComments"
                  ]
                },
                "description": "Turns commenting back on."
              },
              "response": []
            }
          ]
        },
        {
          "name": "deletePost",
          "description": "`POST /instagram/page/deletePost` - delete a media object (post / story / reel / carousel).",
          "item": [
            {
              "name": "Delete a media object",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/deletePost",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "deletePost"
                  ]
                },
                "description": "`mediaId` mandatory -> else reason 4. A single carousel **child** cannot be deleted - only the whole carousel.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/deletePost",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "deletePost"
                      ]
                    },
                    "description": "`mediaId` mandatory -> else reason 4. A single carousel **child** cannot be deleted - only the whole carousel.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"17895695668004550\",\n  \"deleted\": true,\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "createComment",
          "description": "`POST /instagram/page/createComment` - comment as the business account: on a **media object** (top level) or on a **comment** (reply). One endpoint for both, exactly like `/facebook/page/createComment`.",
          "item": [
            {
              "name": "Comment on a media object",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"body\": \"Thanks for all the love, everyone! 🧡\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createComment"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaId` | yes (or `commentId`) | Comment on a media object. Neither valid -> reason 4 |\n| `commentId` | yes (or `mediaId`) | Reply to a specific comment. **If both are sent, `commentId` wins** |\n| `body` | yes | Plain text <=2,200 chars. Missing -> 5, over -> 8 |\n\n`target` in the response echoes whichever id you sent, and `commentId` is the real new comment - use it to hide, delete or private-reply.\n\n> Instagram comments cannot carry media, so there is no `url` / `attachmentId` here (unlike the Facebook Page endpoint).\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"body\": \"Thanks for all the love, everyone! 🧡\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createComment"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaId` | yes (or `commentId`) | Comment on a media object. Neither valid -> reason 4 |\n| `commentId` | yes (or `mediaId`) | Reply to a specific comment. **If both are sent, `commentId` wins** |\n| `body` | yes | Plain text <=2,200 chars. Missing -> 5, over -> 8 |\n\n`target` in the response echoes whichever id you sent, and `commentId` is the real new comment - use it to hide, delete or private-reply.\n\n> Instagram comments cannot carry media, so there is no `url` / `attachmentId` here (unlike the Facebook Page endpoint).\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"target\": \"17895695668004550\",\n  \"commentId\": \"17870913679156914\",\n  \"body\": \"Thanks for all the love, everyone! 🧡\",\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Reply to a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"body\": \"Yes! Sizes 36-45 are all in stock 😊\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/createComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "createComment"
                  ]
                },
                "description": "Send `commentId` instead of `mediaId` to answer one specific person - we post it on the comment's `replies` edge for you.\n\n> Replying to a reply is not possible - Instagram allows a single nesting level, so reply to the parent comment instead."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"body\": \"Yes! Sizes 36-45 are all in stock 😊\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/createComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "createComment"
                      ]
                    },
                    "description": "Send `commentId` instead of `mediaId` to answer one specific person - we post it on the comment's `replies` edge for you.\n\n> Replying to a reply is not possible - Instagram allows a single nesting level, so reply to the parent comment instead."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"target\": \"17870913679156914\",\n  \"commentId\": \"17870913679199999\",\n  \"body\": \"Yes! Sizes 36-45 are all in stock 😊\",\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "hideComment",
          "description": "`POST /instagram/page/hideComment` - hide / unhide a comment on your media.",
          "item": [
            {
              "name": "Hide a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"hide\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/hideComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "hideComment"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `hide` | no (1) | `1` = hide, `0` = unhide |\n\nReversible - unlike deleteComment.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"hide\": 1\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/hideComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "hideComment"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `hide` | no (1) | `1` = hide, `0` = unhide |\n\nReversible - unlike deleteComment.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"17870913679156914\",\n  \"hidden\": true,\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Unhide a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"hide\": 0\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/hideComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "hideComment"
                  ]
                },
                "description": "Brings the comment back into public view."
              },
              "response": []
            }
          ]
        },
        {
          "name": "deleteComment",
          "description": "`POST /instagram/page/deleteComment` - permanent removal of a comment on your own media.\n\n> Liking comments is **not possible** on Instagram (Meta has no such API) - that is why there is no `likeComment` here.",
          "item": [
            {
              "name": "Delete a comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/deleteComment",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "deleteComment"
                  ]
                },
                "description": "`commentId` mandatory -> else reason 4.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/deleteComment",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "deleteComment"
                      ]
                    },
                    "description": "`commentId` mandatory -> else reason 4.\n\nFailures: 2, 3, 4, 6, 7, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"17870913679156914\",\n  \"deleted\": true,\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "privateReply",
          "description": "`POST /instagram/page/privateReply` - one-time private DM in response to a comment on your media. **One per comment, within 7 days.** If the user answers, a normal 24h IG DM window opens.",
          "item": [
            {
              "name": "DM the commenter",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"body\": \"Sent you the details in DM 📩\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/privateReply",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "privateReply"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `body` | yes | <=**1000 bytes** (IG DM limit). Missing -> 5, over -> 8 |\n\nA second private reply to the same comment returns **reason 13**.\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\",\n  \"body\": \"Sent you the details in DM 📩\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/privateReply",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "privateReply"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `commentId` | yes | -> else reason 4 |\n| `body` | yes | <=**1000 bytes** (IG DM limit). Missing -> 5, over -> 8 |\n\nA second private reply to the same comment returns **reason 13**.\n\nFailures: 2, 3, 4, 5, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"17870913679156914\",\n  \"messageId\": \"aWdfZG06MTpnaDoxMjM0NTY3ODkwOjM0\",\n  \"body\": \"Sent you the details in DM 📩\",\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "getPosts",
          "description": "`POST /instagram/page/getPosts` - list the account's published media, or the currently-live stories, or fetch one media object.",
          "item": [
            {
              "name": "List media",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"media\",\n  \"limit\": 25\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `type` | no (`media`) | `media` = published posts/reels/carousels / `stories` = currently-live stories -> else 8 |\n| `limit` | no (25) | 1-100 -> else 8 |\n| `after` | no | Paging cursor |\n| `mediaId` | no | Fetch ONE media object instead (returns `post`). Invalid -> 4 |\n\n**Media fields** - `id`, `caption`, `media_type` (IMAGE / VIDEO / CAROUSEL_ALBUM), `media_product_type` (FEED / REELS / STORY), `media_url`, `permalink`, `thumbnail_url` (videos), `created_time` (**UNIX UTC seconds**, int - Meta's `timestamp`, converted and renamed for parity with Facebook), `like_count` (absent when the owner hides like counts), `comments_count`, `is_comment_enabled`, `children` (carousel items with their own `media_url`).\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"media\",\n  \"limit\": 25\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/getPosts",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "getPosts"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `type` | no (`media`) | `media` = published posts/reels/carousels / `stories` = currently-live stories -> else 8 |\n| `limit` | no (25) | 1-100 -> else 8 |\n| `after` | no | Paging cursor |\n| `mediaId` | no | Fetch ONE media object instead (returns `post`). Invalid -> 4 |\n\n**Media fields** - `id`, `caption`, `media_type` (IMAGE / VIDEO / CAROUSEL_ALBUM), `media_product_type` (FEED / REELS / STORY), `media_url`, `permalink`, `thumbnail_url` (videos), `created_time` (**UNIX UTC seconds**, int - Meta's `timestamp`, converted and renamed for parity with Facebook), `like_count` (absent when the owner hides like counts), `comments_count`, `is_comment_enabled`, `children` (carousel items with their own `media_url`).\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"media\",\n  \"count\": 2,\n  \"posts\": [\n    {\n      \"id\": \"17895695668004550\",\n      \"caption\": \"New arrivals just landed 🛍️ #newin\",\n      \"media_type\": \"IMAGE\",\n      \"media_product_type\": \"FEED\",\n      \"media_url\": \"https://scontent...\",\n      \"permalink\": \"https://www.instagram.com/p/...\",\n      \"created_time\": 1783595700,\n      \"like_count\": 25,\n      \"comments_count\": 4,\n      \"is_comment_enabled\": true\n    },\n    {\n      \"id\": \"17895695668009999\",\n      \"caption\": \"Watch how we make it 🎬\",\n      \"media_type\": \"VIDEO\",\n      \"media_product_type\": \"REELS\",\n      \"media_url\": \"https://scontent...\",\n      \"thumbnail_url\": \"https://scontent...\",\n      \"permalink\": \"https://www.instagram.com/reel/...\",\n      \"created_time\": 1783600000,\n      \"like_count\": 310,\n      \"comments_count\": 22,\n      \"is_comment_enabled\": true\n    }\n  ],\n  \"paging\": {\n    \"after\": \"QVFIU...\",\n    \"hasNext\": true\n  },\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "List live stories",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"stories\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "`type: stories` returns only the stories that are live right now (they vanish after 24h), with the smaller field set: `id`, `media_type`, `media_url`, `permalink`, `created_time`."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"stories\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/getPosts",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "getPosts"
                      ]
                    },
                    "description": "`type: stories` returns only the stories that are live right now (they vanish after 24h), with the smaller field set: `id`, `media_type`, `media_url`, `permalink`, `created_time`."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"stories\",\n  \"count\": 1,\n  \"posts\": [\n    {\n      \"id\": \"17895695668001111\",\n      \"media_type\": \"IMAGE\",\n      \"media_url\": \"https://scontent...\",\n      \"permalink\": \"https://www.instagram.com/stories/...\",\n      \"created_time\": 1783610000\n    }\n  ],\n  \"paging\": {\n    \"after\": \"\",\n    \"hasNext\": false\n  },\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "List media - next page",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"type\": \"media\",\n  \"limit\": 25,\n  \"after\": \"{{after_cursor}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "Resend with `after` while `paging.hasNext` is `true`. `{{after_cursor}}` is filled automatically from the previous response."
              },
              "response": []
            },
            {
              "name": "Get one media object",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getPosts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getPosts"
                  ]
                },
                "description": "With `mediaId` the response has a single `post` object instead of the `posts` array. A carousel also returns its `children`."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\"\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/getPosts",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "getPosts"
                      ]
                    },
                    "description": "With `mediaId` the response has a single `post` object instead of the `posts` array. A carousel also returns its `children`."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"post\": {\n    \"id\": \"17895695668004550\",\n    \"caption\": \"Swipe to see both colours ➡️\",\n    \"media_type\": \"CAROUSEL_ALBUM\",\n    \"media_product_type\": \"FEED\",\n    \"permalink\": \"https://www.instagram.com/p/...\",\n    \"created_time\": 1783595700,\n    \"like_count\": 25,\n    \"comments_count\": 4,\n    \"is_comment_enabled\": true,\n    \"children\": [\n      {\n        \"id\": \"17895695668004551\",\n        \"media_url\": \"https://scontent...\"\n      },\n      {\n        \"id\": \"17895695668004552\",\n        \"media_url\": \"https://scontent...\"\n      }\n    ]\n  },\n  \"reason\": 1\n}"
                }
              ]
            }
          ]
        },
        {
          "name": "getComments",
          "description": "`POST /instagram/page/getComments` - all comments of a media object, or the replies of one comment.",
          "item": [
            {
              "name": "Comments of a media object",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"limit\": 25\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getComments"
                  ]
                },
                "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaId` | yes (or `commentId`) | Comments of a media object. **If both are sent, `commentId` wins** |\n| `commentId` | yes (or `mediaId`) | Replies of one comment |\n| `limit` | no (25) | 1-100 -> else 8 |\n| `after` | no | Paging cursor |\n\n**Comment fields** - `id`, `text`, `username`, `from`, `created_time` (**UNIX UTC seconds**, int - converted and renamed from Meta's `timestamp` for parity with Facebook), `like_count`, `hidden`, `parent_id` (on replies).\n\nThe `id`s plug straight into createComment (as `commentId`, to reply) / hideComment / deleteComment / privateReply.\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
              },
              "response": [
                {
                  "name": "Success",
                  "originalRequest": {
                    "method": "POST",
                    "header": [
                      {
                        "key": "Content-Type",
                        "value": "application/json"
                      }
                    ],
                    "body": {
                      "mode": "raw",
                      "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"limit\": 25\n}",
                      "options": {
                        "raw": {
                          "language": "json"
                        }
                      }
                    },
                    "url": {
                      "raw": "{{base_url}}/instagram/page/getComments",
                      "host": [
                        "{{base_url}}"
                      ],
                      "path": [
                        "instagram",
                        "page",
                        "getComments"
                      ]
                    },
                    "description": "| Field | Mandatory | Rules |\n|---|---|---|\n| `mediaId` | yes (or `commentId`) | Comments of a media object. **If both are sent, `commentId` wins** |\n| `commentId` | yes (or `mediaId`) | Replies of one comment |\n| `limit` | no (25) | 1-100 -> else 8 |\n| `after` | no | Paging cursor |\n\n**Comment fields** - `id`, `text`, `username`, `from`, `created_time` (**UNIX UTC seconds**, int - converted and renamed from Meta's `timestamp` for parity with Facebook), `like_count`, `hidden`, `parent_id` (on replies).\n\nThe `id`s plug straight into createComment (as `commentId`, to reply) / hideComment / deleteComment / privateReply.\n\nFailures: 2, 3, 4, 6, 7, 8, 10-18.\n\n**Delivery: synchronous.** The call goes straight to Meta and this response already carries the real Meta id. No `unique`, no queue, no webhook."
                  },
                  "status": "OK",
                  "code": 200,
                  "_postman_previewlanguage": "json",
                  "header": [
                    {
                      "key": "Content-Type",
                      "value": "application/json"
                    }
                  ],
                  "cookie": [],
                  "body": "{\n  \"status\": \"OK\",\n  \"from\": \"{{from_ig_page}}\",\n  \"target\": \"17895695668004550\",\n  \"count\": 2,\n  \"comments\": [\n    {\n      \"id\": \"17870913679156914\",\n      \"text\": \"Amazing!\",\n      \"username\": \"some_user\",\n      \"from\": {\n        \"id\": \"1234567890\",\n        \"username\": \"some_user\"\n      },\n      \"created_time\": 1783591200,\n      \"like_count\": 3,\n      \"hidden\": false\n    },\n    {\n      \"id\": \"17870913679157777\",\n      \"text\": \"Do you ship abroad?\",\n      \"username\": \"another_user\",\n      \"from\": {\n        \"id\": \"1234567891\",\n        \"username\": \"another_user\"\n      },\n      \"created_time\": 1783592000,\n      \"like_count\": 0,\n      \"hidden\": false\n    }\n  ],\n  \"paging\": {\n    \"after\": \"QVFIU...\",\n    \"hasNext\": false\n  },\n  \"reason\": 1\n}"
                }
              ]
            },
            {
              "name": "Replies of one comment",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"commentId\": \"{{ig_comment_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getComments"
                  ]
                },
                "description": "Send `commentId` to read that comment's replies instead of the media's comments."
              },
              "response": []
            },
            {
              "name": "Comments - next page",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"from\": \"{{from_ig_page}}\",\n  \"mediaId\": \"{{ig_media_id}}\",\n  \"limit\": 25,\n  \"after\": \"{{after_cursor}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                },
                "url": {
                  "raw": "{{base_url}}/instagram/page/getComments",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "instagram",
                    "page",
                    "getComments"
                  ]
                },
                "description": "Keep sending while `paging.hasNext` is `true`."
              },
              "response": []
            }
          ]
        }
      ]
    },
    {
      "name": "5 - Webhooks (what we send you)",
      "description": "These are **not** API endpoints - they are samples of what our worker POSTs at **your** server, so you can point `{{your_webhook_url}}` at your own handler and test it end to end.\n\nThe `sendStatus` webhook applies to **types 1 + 2 only** (the async model). Page and post endpoints (types 3 + 4) return everything in their own response and never send a webhook.\n\nTo receive it, add a **`webhook_url`** field to the connection's `facebook_settings` document (changes take effect within 5 minutes). If it is empty or missing, nothing is sent. One POST per job.\n\n| Field | Description |\n|---|---|\n| `event` | Always `sendStatus` |\n| `from` | The connection id |\n| `facebook_type` | 1 or 2 |\n| `unique` | The id you got in the API response - your correlation handle |\n| `recipient` | The PSID / IGSID |\n| `status` | `sent` = Meta accepted, `failed` = Meta rejected |\n| `meta_id` | The real Meta message id (`m_...`) - empty on failure |\n| `reason` | On failure only: OUR reason code 10-18 |\n\nMatch it to the request by `unique`, then store `meta_id` as the permanent id of the message.",
      "item": [
        {
          "name": "sendStatus - sent (Facebook Messenger)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event\": \"sendStatus\",\n  \"from\": \"8AtRxxxxxxxxxxxxxxxx\",\n  \"facebook_type\": 1,\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"recipient\": \"24031234567890123\",\n  \"status\": \"sent\",\n  \"meta_id\": \"m_AbCdEfGhIjKlMnOpQrStUv\",\n  \"timestamp\": 1783263295\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{your_webhook_url}}",
              "host": [
                "{{your_webhook_url}}"
              ]
            },
            "description": "The happy path: Meta accepted the message. `meta_id` is the real message id - store it, it is the id every later Messenger webhook will use.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": []
        },
        {
          "name": "sendStatus - failed (24h window closed)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event\": \"sendStatus\",\n  \"from\": \"8AtRxxxxxxxxxxxxxxxx\",\n  \"facebook_type\": 1,\n  \"unique\": \"a1b2c3d4e5f6789-9f8e7d6c5b4a321-Xy9Zw8Vu7Tt6Ss5\",\n  \"recipient\": \"24031234567890123\",\n  \"status\": \"failed\",\n  \"meta_id\": \"\",\n  \"timestamp\": 1783263295,\n  \"reason\": 14\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{your_webhook_url}}",
              "host": [
                "{{your_webhook_url}}"
              ]
            },
            "description": "A failure adds OUR `reason` (10-18) and nothing else - no Meta code, no message text. **reason 14** is by far the most common one: the 24-hour messaging window closed, so the customer has to write to you again.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": []
        },
        {
          "name": "sendStatus - failed (Instagram, token expired)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event\": \"sendStatus\",\n  \"from\": \"9BuSyyyyyyyyyyyyyyyy\",\n  \"facebook_type\": 2,\n  \"unique\": \"b2c3d4e5f6789a1-8e7d6c5b4a3219f-Zw8Vu7Tt6Ss5Xy9\",\n  \"recipient\": \"17841400000000000\",\n  \"status\": \"failed\",\n  \"meta_id\": \"\",\n  \"timestamp\": 1783263295,\n  \"reason\": 10\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{your_webhook_url}}",
              "host": [
                "{{your_webhook_url}}"
              ]
            },
            "description": "**reason 10** means the connection's access token was revoked or expired - the client has to go through onboarding again. Show them a 'reconnect' banner rather than retrying.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": []
        }
      ]
    }
  ]
}