Skip to main content
iMessage group chats use the existing messages and conversations endpoints. They are available to identities with an active attached dedicated iMessage line. Shared-service conversations remain 1:1. This is separate from group SMS/MMS: iMessage groups use iMessage conversation IDs and iMessage delivery state.

Start or select a group

Pass 2-8 distinct E.164 phone numbers in to. An admin API key also passes the sending identity as agent_identity_id; an identity-scoped API key always sends as its own identity.
bash
The server normalizes the requested member set before resolving the conversation:
  • One unresolved local group with the same requested members is reused before a remote thread has been established, whether creation is still pending or being retried.
  • One established group with the same best-known members is reused only when its current membership can be verified and still matches the request.
  • If no reusable match remains, a new group conversation is created.
  • If multiple groups match, the request returns 409 ambiguous_group_conversation instead of choosing one. Continue a specific thread by its conversation_id.
A to request never adds or removes members from an existing group. A different member set selects another exact match or creates a separate group. A scalar to value and a one-item to list keep their existing 1:1 behavior. to and conversation_id are mutually exclusive. The 201 response uses the regular Message object. Group-specific fields look like this:
JSON
Each previously unknown participant counts toward both dedicated-line limits: 10 new contacts per rolling hour and 40 per rolling 24 hours. The whole group request is rejected if the line does not have enough remaining slots in either window.

Creation lifecycle

Group creation is asynchronous. The initial 201 means Inkbox stored the local conversation and queued the first message; it does not mean the remote thread is ready yet. Read the conversation or opt groups into the conversation list to inspect group_creation_status: An unconfirmed first send is closed after a 15-minute confirmation window, without assuming that it was never delivered. It retains error_code: "send_outcome_ambiguous". Waiting messages that were never sent are closed with error_reason: "request_not_sent". They do not automatically create a replacement group. If you choose to send again, use a fresh request key and do not blindly repeat the uncertain original. A new attempt can create a separate group if the earlier creation succeeded without confirmation. While the conversation is creating, another send to the same conversation_id or exact to set is stored as another pending message on that local conversation and waits behind the elected creation send instead of initiating creation independently. If the initial attempt fails, the local conversation keeps the same conversation_id and the failed message remains visible in its history with status: "error". Send the next message with that conversation_id to retry creation. A successful retry changes the conversation to ready; later sends continue the newly bound group without creating another local conversation.

Continue the same group

For Companion mode, conversation_id is required to use conversation-only reply permission. Raw to sends cannot borrow that permission. The sponsor must remain in the verified current group; membership changes require fresh sponsorship. Read access and reply readiness are separate, and ordinary send requirements still apply. Keep the conversation_id from the first response and use it for every later send into that exact thread:
JSON
conversation_id is the canonical group key. Do not reconstruct a thread from its participants when you need to continue a specific conversation: membership can change, and more than one real group can have the same members. A send by conversation_id continues that native thread with its verified current membership; all current recipients must pass the send preflight. Group creation and conversation replies support the same 13 expressive send_style values as 1:1 messages. A style can accompany text, one media_urls item, or both:
JSON

Native reply threads

To reply to a specific message within an established group, send conversation_id, reply_to_message_id, and your text or media through the existing messages endpoint. The target can be a participant’s message or a confirmed sent message in that same group. Omit the target for an ordinary group message. Group messages expose nullable reply_to_message_id, thread_id, and thread_root_message_id on message reads and message webhooks. A non-null parent identifies a visible reply; an ordinary message can have its own thread ID before anyone replies. Use sender_number to identify the participant. Retrieve the root and visible replies with Get a reply thread, or Get conversation thread when you already have its ID. A reply thread stays inside the existing group; it does not create another conversation or change its membership. plain_reply_fallback defaults to true: a target known to use SMS/RCS or to have been downgraded can receive an ordinary response in that same group, without native reply metadata linking it to the target. This uses ordinary transport selection, not a separate 1:1 send to each participant. Set plain_reply_fallback: false to require native threading. Missing, inaccessible, pending, failed, or unresolved targets remain errors. Fallback does not automatically retry a rejected native reply, delivery failure, timeout, or uncertain send. See reply behavior.

List and read groups

Existing list endpoints exclude groups by default so current 1:1 callers keep the same result set and pagination. Pass include_groups=true to opt in:
Known conversation IDs work without the list flag:
REST conversation reads return is_group: true, participants, group_creation_status, and null assignment_id, assignment_status, and remote_number fields. MCP conversation reads expose is_group, participants, and the same null assignment/recipient fields, but do not include group_creation_status. Group messages return a participant snapshot. On inbound group messages, sender_number identifies who sent the message and remote_number mirrors that value for compatibility.

Membership semantics

Conversation participants is an append-only, best-known history of E.164 phone numbers observed in the thread. A newly added member may not appear until later group activity, and a member who leaves is not removed from the stored list. Do not use this field as an authoritative current-membership or authorization check. Before an existing-group send or tapback is accepted, Inkbox resolves the thread’s current recipients and applies opt-out and contact-rule checks to each one. There is no API operation to add or remove a group member in V1. Membership changes happen in the native group conversation, and Inkbox updates its best-known participant history as activity reveals changes. After that history gains a member, sending to the original subset can create a separate group instead of continuing this one; use conversation_id whenever thread continuity matters.

Delivery and current limitations

Outbound group messages include one recipients entry per participant. Group delivery transitions are message-level in V1, so the aggregate state is applied to those participant entries together. See iMessage webhooks. Ready groups support tapbacks with the same targeting, replacement, and removal semantics as 1:1 conversations. Group reactions have assignment_id: null, and an inbound group reaction’s remote_number identifies the participant who reacted. Read receipts and typing indicators return 409 operation_not_supported_for_group_conversation. MCP supports group reads, sends, and tapbacks; conversation lists include groups only when requested. Detaching or reassigning the dedicated line leaves the old conversation readable as history to its original organization and identity, but sends and actions on it return 409. A later line owner does not inherit the old group.

Error responses

Use the response’s detail.error to choose the recovery path. Select a specific conversation_id for ambiguous_group_conversation. For group_membership_changed, verify the intended members and repeat the request so matching runs again. Retry group_conversation_not_ready only after the conversation is ready on its current line. Membership-consistency conflicts and group_membership_unavailable may be retried with backoff, while attachment and unsupported-operation conflicts require changing the line or operation instead of retrying unchanged.