{
  "info": {
    "_postman_id": "f4d5e6c0-d1ab-4567-8901-sigfollowapi01",
    "name": "SigFollow Public API",
    "description": "Complete collection of the SigFollow Public API — Meta Cloud API-compatible WhatsApp messaging, plus SigFollow-native Contacts and Blacklist resources.\n\nSet the `base_url` and `api_key` collection variables, then start sending. See https://sigfollow.com/docs/api for narrative documentation.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.sigfollow.com",
      "type": "string",
      "description": "Public API gateway base URL. Use https://api.sigfollow.com in production or your own host for self-hosted deployments."
    },
    {
      "key": "api_key",
      "value": "sflo_live_REPLACE_ME",
      "type": "string",
      "description": "Plaintext API key with prefix sflo_live_. Create one in Admin → Integrations → API Keys. Plaintext is shown once at creation time."
    },
    {
      "key": "phone_number_id",
      "value": "REPLACE_WITH_META_PHONE_NUMBER_ID",
      "type": "string",
      "description": "Meta phone number ID (not a phone number string). Bound to the API key's tenant."
    },
    {
      "key": "waba_id",
      "value": "REPLACE_WITH_WABA_ID",
      "type": "string",
      "description": "WhatsApp Business Account ID."
    },
    {
      "key": "contact_id",
      "value": "REPLACE_WITH_CONTACT_CUID",
      "type": "string"
    },
    {
      "key": "tag_id",
      "value": "REPLACE_WITH_TAG_CUID",
      "type": "string"
    },
    {
      "key": "blacklist_id",
      "value": "REPLACE_WITH_BLACKLIST_CUID",
      "type": "string"
    },
    {
      "key": "Recipient-Phone-Number",
      "value": "REPLACE_WITH_RECIPIENT_PHONE",
      "type": "string",
      "description": "Target WhatsApp phone in E.164 form without the leading +. Server-side normalization strips +, spaces, and dashes so most formats work."
    }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [{ "key": "token", "value": "{{api_key}}", "type": "string" }]
  },
  "item": [
    {
      "name": "Messages",
      "item": [
        {
          "name": "Send message (text)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{Recipient-Phone-Number}}\",\n  \"type\": \"text\",\n  \"text\": { \"body\": \"Hello from SigFollow\", \"preview_url\": false }\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/{{phone_number_id}}/messages",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{phone_number_id}}", "messages"]
            },
            "description": "Send a WhatsApp message. Body shape mirrors Meta Cloud API. Required scope: messages:send."
          }
        },
        {
          "name": "Send message (image by URL)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{Recipient-Phone-Number}}\",\n  \"type\": \"image\",\n  \"image\": { \"link\": \"https://example.com/picture.jpg\", \"caption\": \"Optional\" }\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/{{phone_number_id}}/messages",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{phone_number_id}}", "messages"]
            }
          }
        },
        {
          "name": "Send template message",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{Recipient-Phone-Number}}\",\n  \"type\": \"template\",\n  \"template\": {\n    \"name\": \"order_shipped\",\n    \"language\": { \"code\": \"en_US\" },\n    \"components\": [\n      {\n        \"type\": \"body\",\n        \"parameters\": [\n          { \"type\": \"text\", \"text\": \"Alex\" },\n          { \"type\": \"text\", \"text\": \"TRK-90211\" }\n        ]\n      }\n    ]\n  }\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/{{phone_number_id}}/messages",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{phone_number_id}}", "messages"]
            }
          }
        }
      ]
    },
    {
      "name": "Media",
      "item": [
        {
          "name": "Upload media",
          "request": {
            "method": "POST",
            "header": [],
            "body": {
              "mode": "formdata",
              "formdata": [
                { "key": "messaging_product", "value": "whatsapp", "type": "text" },
                { "key": "file", "type": "file", "src": [] }
              ]
            },
            "url": {
              "raw": "{{base_url}}/v1/{{phone_number_id}}/media",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{phone_number_id}}", "media"]
            },
            "description": "Multipart upload. MIME must match the file's magic bytes; SigFollow rejects mismatches. Required scope: messages:send."
          }
        }
      ]
    },
    {
      "name": "Templates",
      "item": [
        {
          "name": "Create template",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"order_shipped\",\n  \"language\": \"en_US\",\n  \"category\": \"UTILITY\",\n  \"components\": [\n    { \"type\": \"BODY\", \"text\": \"Hi {{1}}, your order {{2}} has shipped.\" }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/{{waba_id}}/message_templates",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{waba_id}}", "message_templates"]
            },
            "description": "Required scope: templates:write."
          }
        },
        {
          "name": "List templates",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/{{waba_id}}/message_templates?name=order_shipped",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{waba_id}}", "message_templates"],
              "query": [
                { "key": "name", "value": "order_shipped", "description": "Exact name filter (optional)" }
              ]
            },
            "description": "Required scope: templates:read."
          }
        },
        {
          "name": "Upload template header media",
          "request": {
            "method": "POST",
            "header": [],
            "body": {
              "mode": "formdata",
              "formdata": [
                { "key": "file", "type": "file", "src": [] }
              ]
            },
            "url": {
              "raw": "{{base_url}}/v1/{{waba_id}}/template_media",
              "host": ["{{base_url}}"],
              "path": ["v1", "{{waba_id}}", "template_media"]
            },
            "description": "Required scope: templates:write. Wraps Meta Resumable Upload — returns { header_handle } for use in components[].example.header_handle when creating an IMAGE/VIDEO/DOCUMENT template."
          }
        }
      ]
    },
    {
      "name": "Contacts",
      "item": [
        {
          "name": "Get contact by phone",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/contacts/by-phone?phone={{Recipient-Phone-Number}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts", "by-phone"],
              "query": [{ "key": "phone", "value": "{{Recipient-Phone-Number}}" }]
            }
          }
        },
        {
          "name": "Get contact by id",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/contacts/{{contact_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts", "{{contact_id}}"]
            }
          }
        },
        {
          "name": "Upsert contact",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"{{Recipient-Phone-Number}}\",\n  \"display_name\": \"Alice Liu\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/contacts",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts"]
            },
            "description": "Required scope: contacts:write. Idempotent on (tenant, phone)."
          }
        },
        {
          "name": "Update contact display name",
          "request": {
            "method": "PATCH",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"display_name\": \"Alice L.\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/contacts/{{contact_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts", "{{contact_id}}"]
            }
          }
        },
        {
          "name": "Delete contact",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/contacts/{{contact_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts", "{{contact_id}}"]
            }
          }
        },
        {
          "name": "Assign tag",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"tag_id\": \"{{tag_id}}\",\n  \"reason\": \"Imported from CRM\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/contacts/{{contact_id}}/tags",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts", "{{contact_id}}", "tags"]
            }
          }
        },
        {
          "name": "Unassign tag",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/contacts/{{contact_id}}/tags/{{tag_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "contacts", "{{contact_id}}", "tags", "{{tag_id}}"]
            }
          }
        }
      ]
    },
    {
      "name": "Blacklist",
      "item": [
        {
          "name": "Check phone",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/blacklist/check?phone={{Recipient-Phone-Number}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "blacklist", "check"],
              "query": [{ "key": "phone", "value": "{{Recipient-Phone-Number}}" }]
            },
            "description": "Required scope: blacklist:read. Returns { phone, blacklisted }."
          }
        },
        {
          "name": "Add to blacklist",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"{{Recipient-Phone-Number}}\",\n  \"reason\": \"Reported as spam\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/blacklist",
              "host": ["{{base_url}}"],
              "path": ["v1", "blacklist"]
            },
            "description": "Required scope: blacklist:write. Same phone twice produces two audit rows."
          }
        },
        {
          "name": "Update blacklist reason",
          "request": {
            "method": "PATCH",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reason\": \"Updated after re-verification\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/blacklist/{{blacklist_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "blacklist", "{{blacklist_id}}"]
            }
          }
        },
        {
          "name": "Delete blacklist row",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/blacklist/{{blacklist_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "blacklist", "{{blacklist_id}}"]
            }
          }
        },
        {
          "name": "Un-blacklist phone (bulk by phone)",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/blacklist/by-phone?phone={{Recipient-Phone-Number}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "blacklist", "by-phone"],
              "query": [{ "key": "phone", "value": "{{Recipient-Phone-Number}}" }]
            },
            "description": "Wipes all blacklist rows for the given phone. Returns { removed: N }."
          }
        }
      ]
    }
  ]
}
