Skip to content
Get Started

Group Photos

Set or clear the Apple-visible photo of an iMessage group chat via API

Set or clear the Apple-visible photo of an existing iMessage group chat. The change is applied on the Sendblue line that serves the group and is verified on the device before the API responds: a success response means the photo (or cleared state) was observed as the actual Apple chat’s current photo, not merely requested. When more than one of your Sendblue numbers is in the group, an eligible number is selected automatically unless you choose one explicitly with from_number.

The device-verified photo is stored as the group’s current photo, so GET /api/v2/groups/{group_id} returns its metadata together with a direct image URL. Replacing or clearing the photo replaces the current stored reference and attempts to delete the previous image; no photo history is exposed through the API, and photos changed directly by group participants in Messages are not synchronized back.

Note: Changing or clearing a photo requires the group to already have an iMessage chat (at least one iMessage has been sent or received in it), and the Sendblue line serving the group must be online and support group photo changes. SMS/RCS group chats do not support Apple group photos.

Group photos are supported on select Sendblue line types. The API checks compatibility automatically; requests for a group served by an ineligible Sendblue line return unsupported_line.

POST /api/v2/groups/{group_id}/photo

Authenticate with either the standard API credentials headers (sb-api-key-id and sb-api-secret-key) or an account-scoped temporary API token returned by POST /v3/auth/tokens, sent as Authorization: Bearer <token>. Line-scoped temporary API tokens cannot perform this account-wide mutation and receive the 403 response described below.

To set a photo, either upload the image bytes as multipart/form-data or provide an image URL as JSON. Clearing uses JSON with photo_url: null.

Multipart fields:

ParameterTypeRequiredDescription
filefileYesJPEG, PNG, or GIF image to set, at most 5 MB and 25 million aggregate decoded pixels
from_numberstringNoWhich of your Sendblue numbers performs the change. Omit to select an eligible number automatically

JSON fields:

ParameterTypeRequiredDescription
photo_urlstring | nullYesPublicly downloadable https URL of a JPEG, PNG, or GIF image at most 5 MB and 25 million aggregate decoded pixels, or null to clear the photo
from_numberstring | nullNoWhich of your Sendblue numbers performs the change. Omit (or pass null) to select an eligible number automatically

The image bytes are fully validated before anything is sent to the device. Uploaded filenames and content types are not trusted. Images are limited to 25 million aggregate decoded pixels, including all frames of an animated GIF. For JSON requests, photo_url must be a direct, publicly resolvable https URL and redirects are not followed. Clearing a photo that is already absent succeeds without changing anything.

When from_number is provided, it must be one of your Sendblue numbers serving this group’s iMessage chat, and the change is performed only through that number: if it cannot act — for example it is offline or does not support group photo changes — the request fails without falling back to another number.

Terminal window
curl -X POST "https://api.sendblue.com/api/v2/groups/sb_group_xxxxxxxx/photo" \
-H "sb-api-key-id: YOUR_API_KEY" \
-H "sb-api-secret-key: YOUR_API_SECRET" \

Add -F "from_number=+15550001111" to require a specific Sendblue number.

Terminal window
curl -X POST "https://api.sendblue.com/api/v2/groups/sb_group_xxxxxxxx/photo" \
-H "sb-api-key-id: YOUR_API_KEY" \
-H "sb-api-secret-key: YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"photo_url": "https://example.com/team-photo.png"
}'
Terminal window
curl -X POST "https://api.sendblue.com/api/v2/groups/sb_group_xxxxxxxx/photo" \
-H "sb-api-key-id: YOUR_API_KEY" \
-H "sb-api-secret-key: YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"photo_url": null
}'
{
"status": "OK",
"data": {
"group_id": "sb_group_xxxxxxxx",
"group_photo": {
"photo_guid": "AAAAAAAA-1111-2222-3333-444444444444",
"url": "https://storage.googleapis.com/..."
},
"from_number": "+15550001111"
}
}
FieldTypeDescription
group_idstringThe group whose requested photo state was verified
group_photoobject | nullThe device-verified current photo; null when the photo was cleared
from_numberstring | nullThe Sendblue number that performed the change

group_photo fields:

FieldTypeDescription
photo_guidstringDevice-verified identifier of the current Apple group photo
urlstringDirect URL for downloading the current photo

The same group_photo object (or null) is returned by GET /api/v2/groups/{group_id}, so the verified photo stays retrievable after the mutation. If Sendblue cannot create the read URL, the request fails instead of returning non-retrievable photo metadata.

Errors generated by this endpoint use a machine-readable error_code alongside a human-readable message:

{
"status": "ERROR",
"error_code": "no_apple_chat",
"message": "This group has no Apple iMessage chat yet. Send the first intended message to the group, then retry."
}

Invalid credentials and rate-limit failures use the standard error envelope and do not include error_code:

{
"status": "ERROR",
"message": "Invalid Credentials"
}

Requests with no credentials return:

{
"message": "Did not get inputs for authorization"
}

A line-scoped temporary-token rejection uses code instead of error_code:

{
"status": "ERROR",
"code": "temporary_token_account_scope_not_allowed",
"message": "This line-scoped temporary token cannot access account-wide configuration."
}
HTTP StatusCodeDescription
400invalid_photo_urlphoto_url is missing, not a string/null, or not a valid https URL
400invalid_group_idgroup_id is not a valid Sendblue group identifier
400invalid_from_numberfrom_number is not a valid phone number string
401Authentication credentials are invalid
403Authentication credentials are missing
403code: temporary_token_account_scope_not_allowedA line-scoped temporary token cannot perform this account-wide mutation
404group_not_foundNo group with this group_id exists for your account
422invalid_photoThe multipart file is missing, the image could not be downloaded, exceeds 5 MB or 25 million aggregate decoded pixels, or is not a valid JPEG, PNG, or GIF image
422no_apple_chatThe group has no Apple iMessage chat yet — send the first intended message to the group, then retry
422sms_rcs_only_groupThe group is served over SMS/RCS, which does not support Apple group photos
422unsupported_lineThe Sendblue line serving this group does not support group photo changes
422from_number_not_participantfrom_number is not one of your Sendblue numbers serving this group’s iMessage chat
429The request rate limit was exceeded — retry with backoff
500internal_errorThe change was verified on the device but could not be recorded, or another internal failure occurred; retrying is safe
502group_photo_update_failedThe requested group photo state could not be verified and recorded
503Authentication is temporarily unavailable — retry shortly
503line_offlineThe Sendblue line serving this group is offline — retry when it reconnects
503group_photo_validation_busyA group photo is already being validated — retry shortly
503group_photo_update_in_progressAnother change is still settling for this group — retry shortly
504verification_timeoutThe resulting state could not be verified in time and may or may not have applied. Wait five minutes before retrying the same request.

Failed requests are never replayed automatically.

Only the current verified photo is referenced and returned alongside the group. Its URL is unlisted but can be downloaded by anyone who has the exact URL while the image exists, so do not treat the URL as a credential or use group photos for sensitive content. Replacing or clearing the photo attempts to delete the superseded image, and the image is stored with a no-store cache policy so a successful deletion takes effect immediately for future downloads. Deletion is best-effort during replacement, so a previous URL can remain reachable if storage cleanup fails. Photos that existed before this feature are not backfilled.

Apple propagates group photo changes to the other members’ devices; when their devices render the new photo is up to Apple and is not guaranteed by this API.