Get a sender profile

Reads one of your sender profiles.

The document mirrors POST /v3/sender-profiles, with three differences that follow from this being a read rather than a request.

channels.sms is a list. Create takes the one market a profile starts in; a profile can go on to send in several, and this reports all of them, each with its own status and its own outstanding compliance.

brand comes back in full, with inherit saying whose it is. On a request { "inherit": true } carries no data because there is nothing to send; here it carries the data, because the point of a read is to say what the profile actually sends under.

There is no campaigns array. A campaign is only ever a registration, so what a read can usefully say about one is whether anything is still owed for it — and that is reported per market, in channels.sms[].compliance.requirements. A profile running on your organization's campaign is asked for none of the campaign fields, so an empty requirements is how an inherited campaign reads.

api_key is never returned here. It is shown once, by create.

A profile belonging to another organization reads as 404, not 403: saying which of the two it is would confirm the id exists.

GET
/v3/sender-profiles/{id}

Response Body

application/json

application/json

application/json

curl -X GET "https://example.com/v3/sender-profiles/497f6eca-6276-4993-bfeb-53cbbbba6f08"
{
  "success": true,
  "data": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "name": "string",
    "short_name": "string",
    "description": "string",
    "api_key": "string",
    "billing": {
      "inherit": true,
      "fallback": true
    },
    "channels": {
      "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
      "sms": [
        {
          "country": "string",
          "number_type": "string",
          "sender_value": "string",
          "status": "PROVISIONING",
          "compliance": {
            "brand": {
              "property1": null,
              "property2": null
            },
            "campaign": {
              "property1": null,
              "property2": null
            },
            "documents": [
              {
                "key": "string",
                "file_name": "string",
                "document_id": "b792e8ae-2cb4-4209-85b9-32be4c2fcdd6"
              }
            ]
          }
        }
      ],
      "whatsapp": {
        "waba_id": "string",
        "phone_number_id": "string",
        "solution_id": "string",
        "owner_business_id": "string",
        "status": "PROVISIONING"
      },
      "rcs": {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "status": "PROVISIONING",
        "phone_number": "string",
        "display_name": "string",
        "description": "string",
        "agent_use_case": "string",
        "brand_name": "string",
        "privacy_policy_url": "string",
        "terms_and_conditions_url": "string",
        "website_url": "string",
        "brand_color": "string",
        "brand_phone_number": "string",
        "customer_support_phone_number": "string",
        "brand_email": "string",
        "customer_support_email": "string",
        "contact_name_and_title": "string",
        "company_ein": "string",
        "entity_type": "string",
        "official_address": {
          "street": "string",
          "city": "string",
          "state": "string",
          "postal_code": "string",
          "country": "string"
        },
        "brief_company_description": "string",
        "opt_in_process_description": "string",
        "start_message": "string",
        "help_message": "string",
        "stop_message": "string",
        "sample_messages": [
          "string"
        ],
        "created_at": "2019-08-24T14:15:22Z"
      }
    },
    "compliance": {
      "brand": {
        "property1": null,
        "property2": null
      },
      "campaign": {
        "property1": null,
        "property2": null
      },
      "documents": [
        {
          "key": "string",
          "file_name": "string",
          "document_id": "b792e8ae-2cb4-4209-85b9-32be4c2fcdd6"
        }
      ]
    },
    "created_at": "2019-08-24T14:15:22Z"
  },
  "error": {
    "code": "string",
    "message": "string",
    "details": {
      "property1": [
        "string"
      ],
      "property2": [
        "string"
      ]
    },
    "doc_url": "string"
  },
  "meta": {
    "request_id": "string",
    "timestamp": "2019-08-24T14:15:22Z",
    "version": "string"
  }
}
Empty
Empty
{
  "success": true,
  "error": {
    "code": "string",
    "message": "string",
    "details": {
      "property1": [
        "string"
      ],
      "property2": [
        "string"
      ]
    },
    "doc_url": "string"
  },
  "meta": {
    "request_id": "string",
    "timestamp": "2019-08-24T14:15:22Z",
    "version": "string"
  }
}
{
  "success": true,
  "error": {
    "code": "string",
    "message": "string",
    "details": {
      "property1": [
        "string"
      ],
      "property2": [
        "string"
      ]
    },
    "doc_url": "string"
  },
  "meta": {
    "request_id": "string",
    "timestamp": "2019-08-24T14:15:22Z",
    "version": "string"
  }
}

List sender profiles GET

Lists the sender profiles under your organization, newest first, paginated with `page` and `page_size`. Each entry is the same document `GET /v3/sender-profiles/{id}` returns, with one difference: **listed markets carry no `compliance`**. Working out what a market still owes means a catalog lookup and a document read per market, and doing that for every profile on a page would turn one request into dozens to answer a question you did not ask. Read a single profile for that. `compliance` being **absent** is not the same as it being **empty**. Absent means it was not worked out here; empty means the market owes nothing. `api_key` is never returned. It is shown once, by create.

Create a sender profile POST

Creates a sender profile under your organization. A profile is a customer of yours: it sends under its own or your identity, and your customers never see Sent. ## The minimum `{ "name": "Example Retail", "short_name": "Example" }`. `short_name` is the SMS sender id and is required. Identity, inbox, opt-out list and billing come from your organization, so the profile is usable immediately with no compliance work. **A sender is not one of them.** The brand and the campaign can be inherited; a number cannot. A profile either has a sender of its own — `channels.sms` — or it has none and terminates through the shared routes for that country. ## Saying what a profile owns Every capability is one of three things, and there is no flag per state: - **Its own** — supply the capability's fields. Data is what owning looks like. - **The organization's** — `{ "inherit": true }`, with nothing else. - **None** — omit the block. There is no `"inherit": false` that also carries no data. A second way to say the same thing would let a request contradict itself. Inheriting needs no id. A customer has exactly one brand, so `brand` resolves without one. **The campaign has no block of its own.** It is only ever a registration, and every field of one is something a specific market demands — so it lives in `compliance`, alongside the rest of what that market asks for, and it says whose it is there too: `"compliance": { "inherit": true }` runs the profile on your organization's campaign and stops this call asking for any campaign field. Omitted, or `false`, gives the profile its own; inheriting takes *all* of your organization's, because inheritance resolves an owner rather than a single row. A profile with a `brand` of its own **cannot** inherit the campaign, and asking is refused with `400`: a campaign is filed against a brand registration, and your organization's campaign is filed against your organization's brand rather than this profile's. Inherit both, or own both. `channels.sms` is the market the profile starts in — one `country` and `number_type`. It decides what else this call asks for: the compliance catalog is keyed on that pair, and it determines which fields `brand` accepts and what `compliance` answers for. A profile is a tenant, not a market, so it can go on to send in several — but through `POST /v3/channels/sms` with the `x-profile-id` header, one market and its compliance at a time. Reads return every market as `channels.sms[]`, so the read shape is a list even where this one is not. `brand` is required when `number_type` is `TEN_DLC` — inherited or its own. A 10DLC registration has nothing to attach to without one, and no later call can supply it, so omitting it is refused with `400` rather than reported as outstanding. ## Use cases and volume A TCR campaign declares one to five `use_cases`, each with its own `sample_messages` — TCR attributes samples to the use case they illustrate, so they travel together. How that set registers is derived from `volume` and never declared. Below the low-volume threshold the campaign registers as `LOW_VOLUME` with every entry as a sub-use-case; above it, one entry registers as that use case outright and several register as `MIXED` with sub-use-cases. `MIXED` and `LOW_VOLUME` are therefore refused as `use_case` values: they describe the shape of a set, which is ours to work out. **Leaving `volume` out is accepted and costs more.** An absent value registers the campaign at the standard tier, which carries the higher fee — so say so when a campaign is low volume. Sole proprietor brands are the exception: their fee is fixed by entity type, and volume only decides the use case. ## Compliance `brand` is captured identically in every country. Everything a specific market demands on top of it — including every field of the campaign — goes in `compliance`, as key/value entries whose keys depend on the sender's country and type. US `TEN_DLC` registers with The Campaign Registry and asks for a substantial set; an alphanumeric sender may pre-register with documents, or need nothing at all. You do not have to know any of it. Omit `compliance` and the response lists exactly what is outstanding, with types and accepted values — or call `GET /v3/compliance/requirements` first. Anything Sent supplies on your behalf is never asked for, and is rejected if sent. Requirements can be conditional, and the condition is published as `required_when` so you can render a form from it rather than discover the rule by being rejected. Every US `TEN_DLC` campaign field carries `compliance.inherit != true` — send `"inherit": true` and none of them is asked for or accepted, because the profile is running on your organization's campaign. ## Uploading documents Send `application/json` for everything except a market that pre-registers a sender with supporting documents. For those, send `multipart/form-data` instead: put this entire document — unchanged — in a single field named `profile`, and attach each file under a field named after the compliance key it satisfies. Individual form fields per property are not read; the payload is always the one `profile` field. ## WhatsApp and RCS Neither can be inherited, so neither takes an `inherit`: the profile's WhatsApp account and RCS agent are its own or it has none. Sharing your organization's would share its inbox and its throughput, which makes the two indistinguishable to a recipient. `channels.whatsapp` names one of the accounts shared into your organization, and takes the two identifiers nothing else can supply: `waba_id`, because your organization holds one account per client, and `phone_number_id`, because an account may hold several numbers and choosing for you would decide which of your customer's numbers their traffic leaves from. Everything else is resolved from your organization — the Multi-Partner Solution the account arrived through, the client business portfolio that owns it, the access token and that token's expiry. None of them is accepted here: the first two are Meta's answer about provenance, so a value you sent could assert a partnership Meta disagrees with, and the token is minted per client business and rotates roughly every sixty days. `phone_number_id` is optional. Omit it to connect the account now and settle the number later — the channel reads as `provisioning` and the profile keeps sending from your organization's account until a number is named. `POST /v3/channels/whatsapp` connects an account to an existing profile and resolves the same fields the same way. An account of its own needs a sender of its own, so `channels.whatsapp` requires `channels.sms`. A profile sending SMS on your organization's sender shares that inbox and opt-out list, and is not a separate tenant to give an account to — asking is refused with `400`, before your organization is asked to resolve anything. `channels.rcs` records the agent. A carrier approval no API call can trigger is arranged offline, so the capability reports `awaiting_submission` until it is. `rcs.brand_id` is Google's identifier and is unrelated to the top-level `brand`. ## Responses `201` when the profile is complete on return — the fully-inherited case, where nothing needs registering. `202` when something is still provisioning, with per-capability status and outstanding requirements. `409` when the WhatsApp account supplied is already recorded. `400` covers a wrong value as well as a missing one: a missing brand under `TEN_DLC`, an unknown compliance key, a bad type, a sender id the market does not allow, or a `waba_id` that is not one of the accounts shared into your organization.