Media
Images, GIFs, audio and video in notifications, by platform.
What each platform supports
| Content | Android | iOS |
|---|---|---|
| Image (JPG, PNG) | Yes, large image. No code in the app | Yes, with a Notification Service Extension |
| Animated GIF | Shown static (poster) | Animated (extension) |
| Audio | Not as an attachment: it opens in the app | Playable (extension) |
| Video | The poster is shown and it opens in the app | Playable (extension) |
| Large icon | Yes (largeIcon) |
Not applicable |
Image carousel
A notification can carry 2 to 5 images that the user swipes through. Each image can have a short title (up to 40 characters, text or per language) and its own link:
"media": {
"type": "carousel",
"items": [
{ "mediaId": "01J…A", "title": { "es": "Zapatillas", "en": "Sneakers" }, "deepLink": "https://shop.com/p/1" },
{ "mediaId": "01J…B", "title": "Backpack", "deepLink": "myapp://product/2" },
{ "url": "https://cdn.shop.com/cap.jpg" }
]
}
| Where | What it looks like |
|---|---|
| Android with the Pushtifly SDK | One image at a time with ‹ › buttons and the title below. Tapping the image opens its link. It arrives as a data message so the SDK can draw it even when the app is closed |
| iOS with the SDK and both extensions | A thumbnail with the first image; on long press, a swipeable carousel with a View button that opens the visible image's link |
| Flutter and React Native / Expo | Android: same as the native SDK, if the app registers the background handler (androidCarousel). iOS: with both extensions |
| Capacitor and Cordova | Android: the first image. iOS: with both extensions |
| No SDK, browsers and Huawei | Only the first image, as a regular image notification |
The SDK declares the carousel capability; the send preview warns how many devices will only see the first image (carousel_partial). In the dashboard, choose Image carousel in the editor's media block.
The images and their titles count toward the message's 4 KB limit: with 5 images, keep titles short.
iOS: Notification Content Extension
On iOS the carousel needs, besides the Notification Service Extension (which downloads the images), a Notification Content Extension (which shows them):
- In Xcode, File → New → Target → Notification Content Extension.
- Add the Swift package's
PushtiflyNotificationContentproduct to the target and make the class:import PushtiflyNotificationContent class NotificationViewController: PushtiflyNotificationContentViewController {} - In the target's
Info.plist, underNSExtension → NSExtensionAttributes:UNNotificationExtensionCategory=PUSHTIFLY_CAROUSEL,UNNotificationExtensionUserInteractionEnabled=YES,UNNotificationExtensionInitialContentSizeRatio=0.6. DeleteNSExtensionMainStoryboardand setNSExtensionPrincipalClass=$(PRODUCT_MODULE_NAME).NotificationViewController. - In the app:
PushtiflyOptions(…, notificationServiceExtension: true, notificationContentExtension: true).
When the user taps View, your app receives the open with that image's deepLink (the SDK resolves it).
Upload files
From Media in the panel or with POST /v1/media (multipart, field file). Pushtifly processes each file: it optimizes it, generates a poster for GIFs and videos, and a thumbnail. When the status becomes ready, use its mediaId:
"media": { "type": "image", "mediaId": "01J…" }
You can also use an external https URL: "media": { "type": "image", "url": "https://…" }.
Limits
| Type | Maximum size |
|---|---|
| Image and GIF | 10 MB |
| Audio | 5 MB (up to 2 minutes) |
| Video | 50 MB (up to 2 minutes) |
On top of that, total storage depends on your plan.
Recommendations:
- Images under 1 MB, in a 2:1 ratio for Android.
- On iOS, the extension has a few seconds to download the file: the lighter, the better.
iOS: the extension
Without a Notification Service Extension, iOS shows the notification without the attachment. See Native iOS.
Pushtifly sets mutable-content: 1 and the URL in _ph.media.url.