How a message is delivered
- The shell checks that the target app accepts the action from your app (see Accepting messages). If it doesn’t, the answer is
not_acceptedand the target is never opened. - The first time your app messages a given app, the shell asks the user (“Let CV talk to Notes?”). Once they allow it, your app can message that app again without asking, whatever the action. Permission is one way: Notes messaging CV is asked separately.
- If the target is open, the message is delivered in the background. If it is closed, the shell opens it in the foreground first.
- The target’s handler runs and its return value becomes your
result.data.
Opening a closed app, or bringing an open one forward with
focus, should follow a tap. If the user didn’t just press something, the shell asks again even for a pair they already allowed. A background app can’t open other apps.Sending
string
required
The target app’s slug.
string
required
What you’re asking for, such as
notes.create. Letters, digits, ., _ and -, up to 64 characters.unknown
Any JSON value, up to 256 KB serialized.
boolean
default:"true"
Open the target if it is closed. With
false, a closed target answers not_open.boolean
default:"false"
Bring the target forward even when it is already open, for example so the user can pick something in it.
boolean
default:"false"
When the target answers, switch back to your app. This only happens if the target was brought forward for this message and is still on screen.
number
default:"30000"
How long to wait for the answer once the message is delivered, up to 300000. Time spent on the permission prompt or opening the target doesn’t count.
sendToApp never rejects. It resolves with one of these:
unknown
What the target’s handler returned.
boolean
The message was delivered, but this shell can’t send an answer back (TV).
Receiving
onAppMessage(action, handler) registers a handler and returns an unsubscribe function. useAppMessage(action, handler) does the same for the lifetime of a component and always calls the latest handler. Pass '*' to handle every action that has no handler of its own.
The handler receives:
{ slug: string; name?: string }
The sending app. The shell sets this, so the sender can’t impersonate another app.
string
The requested action.
unknown
The sender’s payload.
boolean
true when your app was opened to receive this message.handler_failed.
Register handlers early, at startup or in the screen that handles the action. The shell holds messages for your app until the first handler is registered. A message for an action without a handler waits 5 seconds for one, so a screen that loads lazily still gets it, and is then answered no_handler.
Accepting messages
An app only receives the actions it declares. The declaration is part of the app’s record in the catalogue:string | Record<string, string>
How the permission prompt names the action, as one string or one per language.
string[]
Only these apps (by slug) may send the action. Leave it out to accept any app.
boolean
default:"true"
With
false, the action is only delivered while your app is already open.You can’t set this from your app’s code yet. Ask the cskn team to add the actions your app accepts.
Errors
Surfaces
Check ahead of time with
getAppMessagingAvailability(), which resolves { available, replies }.