# FCM payload builder and validator

Updated 2026-10-22. Free tool, no account: https://notifly.io/tools/fcm-payload-builder

Fill in the form to get a Firebase Cloud Messaging HTTP v1 message with its Android, iOS (APNs) and web overrides, and the curl command for the messages:send endpoint. Or paste a message you already have and the validator checks it against the FCM REST reference: one target, known field names, string data values, reserved keys and the size limit.

FCM counts the keys and values of the notification and data payload against a 4096-byte limit, or 2048 bytes for a message sent to a topic. Every data value must be a string, and FCM rejects field names it does not know.

## How to use it

1. **Pick the target.** A Firebase Installation ID (fid), a registration token, a topic or a topic condition: exactly one.
2. **Write the message.** Title, body and image go in notification; your own key=value pairs go in data, as strings.
3. **Add platform overrides.** Android priority, TTL and channel; the iOS badge and sound; a web click link.
4. **Send it.** Copy the curl request, set ACCESS_TOKEN to an OAuth 2.0 token for your service account and PROJECT_ID to your Firebase project, and run it.

## Limits this tool checks

| Limit | Value | Source | Checked |
| --- | --- | --- | --- |
| FCM message payload, keys and values (notification and data messages) | 4096 bytes | [Firebase: FCM message types](https://firebase.google.com/docs/cloud-messaging/customize-messages/set-message-type) | 2026-10-21 |
| FCM message payload sent to a topic | 2048 bytes | [Firebase: FCM error codes (message too big)](https://firebase.google.com/docs/cloud-messaging/error-codes) | 2026-10-21 |
| Topics in one FCM condition | 5 topics | [Firebase: Send messages to topics](https://firebase.google.com/docs/cloud-messaging/send-topic-messages) | 2026-10-21 |
| FCM android.ttl (4 weeks) | 2419200 seconds | [Firebase: FCM REST API, projects.messages](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages) | 2026-10-21 |

## Use it from code, no key

`POST https://notifly.io/api/tools/validate-fcm` answers JSON, or Markdown with `Accept: text/markdown`. OpenAPI: https://notifly.io/api/tools/openapi.json.

```bash
curl -s https://notifly.io/api/tools/validate-fcm \
  -H "Content-Type: application/json" \
  -d '{"message":{"topic":"news","notification":{"title":"Hi","body":"Breaking"},"data":{"articleId":"42"}}}'
```

## Frequently asked questions

### What is the maximum FCM payload size?

4096 bytes for most messages and 2048 bytes for messages sent to topics, counting both the keys and the values. The Firebase console's composer is stricter still.

### Why does FCM reject my data payload?

Data values must be strings, so send numbers and JSON as strings. Some keys are reserved: "from", "message_type" and any key starting with "google." or "gcm.notification.".

### What is the difference between token and fid?

Firebase's REST reference now marks token as deprecated in favour of fid, a Firebase Installation ID; during the transition the token field also accepts an FID. A message still needs exactly one target: token, fid, topic or condition.

### How long does FCM keep a message for an offline device?

Up to android.ttl, written as a duration string such as "3600s". The maximum and the default are 4 weeks; set it to "0s" to send the message immediately.

### Can I call the validator from my own code?

Yes. POST the send body to https://notifly.io/api/tools/validate-fcm. It needs no key and returns the report as JSON, or Markdown when you send Accept: text/markdown. It allows 30 requests a minute and 300 a day per address.
