Guides
FinBaze never emails your users on its own for a company on your platform. It creates a message, routes it by who should deliver it, and tells you. This guide is the working path; Messages has the full rules and the message catalogue lists every type.
1. Subscribe#
Create a webhook endpoint with message.created and message.unacknowledged (see Events and webhooks):
mutation {
createPlatformWebhookEndpoint(input: {
url: "https://example.com/finbaze"
eventTypes: ["message.created", "message.unacknowledged"]
}) { endpoint { id } signingSecret }
}
signingSecret is shown once. Verify every delivery with it (receivers in Node, Python and PHP are in the sample apps).
2. Deliver#
data.object of message.created is the message. It already has the text for each channel (content.push, content.in_app, content.email, content.sms) and a deep_link your app routes to. Deliver in your own channel, then acknowledge:
mutation Ack($id: ID!) {
acknowledgeMessage(input: { id: $id, channel: "push", outcome: "delivered" }) { id status acknowledgedAt }
}
Dedupe on dedupe_key; do not deliver after expires_at. Acknowledge at least the messages with ack_required: critical messages and those that serve as evidence (invoices and reminders you deliver). Use acknowledgeMessages for up to 100. outcome: "failed" tells FinBaze you could not deliver; the message stays unacknowledged and you get message.unacknowledged after ack_deadline.
3. Choose who sends what#
mutation {
setPlatformMessageRouting(input: { scope: "category", category: "tax_deadline", routing: "partner_delivers" }) { id routing }
}
routing is partner_delivers (the default for notifications), finbaze_sends, both or suppress. A rule applies to everything (scope: "all"), one category or one type, for the platform or for one company (profileId). The most specific rule wins. finbaze_sends needs a verified sender domain for your platform; without one the message falls back to partner_delivers. platformMessageRouting lists your rules, and clearPlatformMessageRouting removes one.
Lifecycle, billing and FinBaze account-security messages are never delivered for platform companies and cannot be changed (ROUTING_NOT_CHANGEABLE).
4. Settings#
mutation {
updatePlatformMessageSettings(input: { quietHoursStart: "22:00", quietHoursEnd: "07:30", quietHoursTimezone: "Europe/Amsterdam", digestHourLocal: 8, brandName: "Acme Books" }) {
digestHourLocal quietHoursStart brandName
}
}
Critical messages ignore quiet hours and limits. More than 20 messages per person per hour, or 3 of one type, fold into an hourly digest.
5. Read the log#
query { platformMessages(filter: { unacknowledgedOnly: true, limit: 50 }) { id type priority status routing routingReason ackDeadline } }
routingReason tells you why: catalogue_default, platform_category, company_override, hard_rule, feature_hidden. resendPlatformMessage queues a message again.
Push notifications#
FinBaze sends push only to its own mobile app, for companies that are not on a platform. For a platform company you send the push yourself from message.created. On mobile, the push can carry an intent that opens the right component; see Mobile.
Pitfalls#
- Treating a webhook delivery as unique: deliveries are at least once.
- Forgetting to acknowledge critical messages: after the deadline FinBaze raises
message.unacknowledged, and withcriticalEmailFallbackon it may email the user itself. - Routing to
finbaze_sendswithout a verified sender domain.