MyComm docs
Menu

Partners

Partners

Give your own users messaging through MyComm with partner lines, one partner key and one API.

If you run a platform whose users each need their own sending (an ERP for dealers, for example), you become a partner. A partner owns lines, not accounts: each line lives in your user's own MyComm account, with the user's own phones, and the user owns that account. You send and read through the line; the user manages the phones and channels.

Two surfaces, one key#

A partner key (mc_partner_...) works on two surfaces:

Surface What it does
/partner/v1 Creates, lists, changes and detaches your lines, and reports usage. See the Partner API reference.
/v1 with MyComm-Line: <line id> Sends and reads messages and conversations of that one line.

The partner's own account is reached with an ordinary account key of that account, never with the partner key.

Create a line#

curl -sS -X POST "$MYCOMM_URL/partner/v1/lines" \
  -H "Authorization: Bearer $MYCOMM_PARTNER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_ref": "dealer-4821", "name": "Order updates", "user_number": "+923001234567"}'

With the SDKs:

$line = $partner->partner->lines->create(external_ref: 'dealer-4821', name: 'Order updates', user_number: '+923001234567');
const line = await partner.partner.lines.create({ external_ref: 'dealer-4821', name: 'Order updates', user_number: '+923001234567' });

external_ref is your own id for the line, unique among your live lines: a second line with the same one answers 409 EXTERNAL_REF_TAKEN with the existing line in details.line_id. Detaching a line frees its external_ref, so you can make a new line for the same customer later. The line starts in a new, empty account that becomes your user's account when they connect a phone. user_number is only a hint for that step: a line never joins an account that already has the number unless a code sent to the number says so, and the answer looks the same either way.

Send through the line#

Send the line's id in MyComm-Line with the partner key:

curl -sS -X POST "$MYCOMM_URL/v1/messages" \
  -H "Authorization: Bearer $MYCOMM_PARTNER_KEY" \
  -H "MyComm-Line: 0198e0aa-3b10-7c52-8a41-5d2f9e7b1c01" \
  -H "Content-Type: application/json" \
  -d '{"to": "+923009998877", "body": "Your order has shipped"}'

The SDKs send the header for you: $partner->forLine($lineId)->messages->send(...) in PHP (and MyComm::forLine($lineId) in Laravel), partner.forLine(lineId).messages.send({...}) in Node.

Header Answer
Missing 400 LINE_CONTEXT_REQUIRED
Not a UUID 400 INVALID_HEADER
A line of another partner, a detached line or no line 403 LINE_CONTEXT_INVALID (the same answer for every case)

With the header a partner key may send and batch messages, list, read and cancel them, read conversations and their messages, and read the line (GET /v1/lines/{id}). Everything else on /v1 (channels, phones, contacts, settings, keys, webhooks, other lines) answers 403 PARTNER_ROUTE_NOT_ALLOWED: those belong to your user. Every action is recorded as done by your partner key, in your user's account.

POST /partner/v1/lines/{id}/links (links:write) makes a short-lived link to MyComm's hosted page for the line, the same link and fields as hosted connect with your partner key. purpose says what the page does:

Purpose What your user does there
connect The first phone. The page asks for their number (pre-filled with user_number). A number with no MyComm account, or "connect my phone", goes on to pairing, and the line's empty account becomes your user's. A number that already has an account gets a code; with it the line joins that account, and its owners are told, with 24 hours to undo it.
add_channel One more SIM: it joins the line as its last backup.
replace_device A new phone for a lost one (replaces_device_id): its numbers move to the new phone and the old one is removed.
manage, claim The hosted manage page.

GET /partner/v1/links/{id} (lines:read) reads a link, DELETE /partner/v1/links/{id} revokes it. Detaching the line ends all its open links.

With the SDKs: $partner->partner->lines->links->create($lineId, purpose: 'connect', return_url: ..., allowed_origins: [...]) (PHP), partner.partner.lines.links.create(lineId, { purpose: 'connect', return_url, allowed_origins }) (Node), and partner->links->get($id) / revoke($id). In Laravel, <x-mycomm-connect :line="$lineId" purpose="connect" /> creates the link for the current page and renders the widget in one step.

Change or detach a line#

PATCH /partner/v1/lines/{id} changes the name and the channel types your user may connect; external_ref never changes. DELETE /partner/v1/lines/{id} detaches the line: it is archived, its open conversations move to the account's Direct line, and your user keeps the account, the phones, the channels and the history. The header stops working for that line. You get line.detached once. A detached line stays archived for good, and its sponsorship ends.

Sponsorship#

You may pay for what a line uses: sponsorship on POST or PATCH /partner/v1/lines/{id} takes channel_fee_cover {type: n} (the fee of the first n numbers of that type on the line), message_allowance {type: n} (messages per cycle; SMS counts segments), cycle_days (default 30) and on_exhausted (hold, the default, or allow_user_overage, which lets your user's own bought messages take over). Set your default terms once with PUT /partner/v1/sponsorship-defaults; a new line that names no sponsorship gets them, and sponsorship: null means none. (SDKs: partner->sponsorshipDefaults->get() / put(...).)

At 80% of an allowance you get line.quota_low, at 100% line.quota_exhausted, once per cycle and type; further messages of that type wait with hold_reason sponsor_quota_exhausted until the next cycle, and the line status shows quota_exhausted. PATCH with sponsorship: null ends it: the numbers it paid for keep sending for 14 days of grace, then stop sending (hold_reason unpaid) until billing is sorted out. Nothing is ever disconnected. GET /partner/v1/usage reports each of your lines.

Line status and events#

GET /partner/v1/lines/{id}/status tells you how a line is doing now: state is not_connected until your user's first number is verified on it, then connected, or needs_attention with needs_attention_reasons (device_offline when every phone of the line is offline, sim_missing, no_sender, quota_exhausted, number_disputed). It also counts the line's numbers per channel type (total, healthy) and says when it last sent and received. In the SDKs: $partner->partner->lines->status($lineId) (PHP), partner.partner.lines.status(lineId) (Node).

You do not need to poll it. Create a webhook endpoint on your own account (POST /v1/webhook-endpoints with an account key of your partner account) with partner_lines: true: it then also receives the events of your partner lines (line.connected once when the first phone is live, line.needs_attention when the line needs your user or a new reason appears, line.recovered, line.detached, line.quota_low, line.quota_exhausted, line.recovery_requested, and the message events of those lines), and nothing else of your users' accounts. Only events that carry the line_id of one of your partner lines reach it: it gets no device.*, channel.*, account.* or contact.* events of your users' accounts (the line status events tell you what you need of their phones and numbers). Narrow it with line_ids, which may name your partner lines. While your partner access is revoked or suspended these deliveries are kept as dead (partner_inactive) and can be replayed once it returns.

Account recovery#

When someone who lost their number asks to recover the account of one of your lines, you get line.recovery_requested with recovery_request_id, the name and new number they gave and waiting_until. If you know this person, say so with POST /partner/v1/lines/{id}/vouch and {recovery_request_id}, using your line of that account. MyComm staff see your answer when they decide. It is never required and never enough alone: nothing changes before the 7-day wait is over and staff approve. A repeat answers the same, and a decided request answers 409 INVALID_STATE.

Keys#

A partner key reaches every line of its partner and can be made read-only. Rotate it like any key: create the new one, deploy it, then revoke the old one; lines never depend on a key. See Authentication.