NX CreativeNX CreativeDocs
Scriptsnx_phone

Events

Client and server events nx_phone raises for other resources, with their payloads.

Every event on this page is local to one side. Listen with AddEventHandler in a script on that side. None of them is a net event, so a client cannot raise or hear the server ones, and none carries a passcode or session secret.

Client events

nx_phone:opened

The phone came up on this client. The argument is the id of the handset that opened.

AddEventHandler('nx_phone:opened', function(phoneId)
    -- hide your own HUD element while the phone is up
end)

nx_phone:closed

The phone was put away. The argument is the reason, for example 'user', 'toggle', 'esc', 'death', 'vehicle', 'pausemenu', 'battery', 'dropped', 'placed', 'disabled', 'blocked' (a can-open hook refused), 'locked', 'server', 'api', or the reason a resource passed to ClosePhone.

AddEventHandler('nx_phone:closed', function(reason)
    print('phone closed: ' .. tostring(reason))
end)

Server events

nx_phone:sdkReady

Fires once, a second after nx_phone starts. Everything other resources register with the phone (apps, sites, hotlines, service routers, Live Activities, phone disables) is lost when it restarts, so register from this event as well as from your own start.

local function register()
    if GetResourceState('nx_phone') ~= 'started' then return end
    exports.nx_phone:RegisterHotline('555-0190', { label = 'Downtown Cab Co.' })
end

AddEventHandler('nx_phone:sdkReady', register)
AddEventHandler('onResourceStart', function(res)
    if res == GetCurrentResourceName() then register() end
end)

nx_phone:server:messageSent

A text message was sent, by a player or through the SendMessage export.

AddEventHandler('nx_phone:server:messageSent', function(m)
    -- m.messageId, m.conversationId
    -- m.from            the sender's number
    -- m.to              list of the other numbers in the thread
    -- m.hasAttachments  boolean
    -- m.blocked         true in a 1:1 thread whose recipient blocked the sender (they never see it)
end)

nx_phone:server:messageToVirtual

A player texted a hotline. The hotline's onMessage handler gets the same table.

AddEventHandler('nx_phone:server:messageToVirtual', function(m)
    -- m.from, m.to (the hotline), m.text
    -- m.conversationId, m.messageId, m.hasAttachments
    -- m.source          the sender's server id, when they are online
    -- m.attachments     { { url, kind = 'photo' | 'video' } ... }
    -- m.choice          { id, label, messageId } when they tapped one of your reply buttons
end)

nx_phone:server:messageRead

A player read a hotline's messages. The hotline's onRead handler gets the same table.

AddEventHandler('nx_phone:server:messageRead', function(r)
    -- r.conversationId, r.hotline, r.upToId (the newest message read)
    -- r.number          the reader's number
    -- r.readAt          epoch ms
    -- r.source          the reader's server id
end)

nx_phone:server:notificationTapped

A player opened a notification: the banner, the Notification Centre or the lock screen. sourceEvent is the tag you gave Notify, or your resource's name.

AddEventHandler('nx_phone:server:notificationTapped', function(n)
    -- n.id, n.phoneId, n.source, n.appId, n.threadKey, n.category, n.title
    -- n.deepLinkApp, n.deepLinkPayload, n.sourceEvent
end)

nx_phone:server:npcCallChoice

A player picked a reply on a scripted NPC call. The script's onChoice gets the same table.

AddEventHandler('nx_phone:server:npcCallChoice', function(c)
    -- c.callId, c.hotline, c.number (the player's), c.choice, c.label, c.step
end)

nx_phone:server:npcCallEnded

A scripted NPC call ended.

AddEventHandler('nx_phone:server:npcCallEnded', function(c)
    -- c.callId, c.hotline, c.number, c.reason, c.answered, c.step
end)

nx_phone:server:notificationSent

A notification was stored on a handset. The body is never included.

AddEventHandler('nx_phone:server:notificationSent', function(n)
    -- n.id, n.appId, n.phoneId, n.title
end)

nx_phone:server:callStarted

A voice call got a call id. It fires before anything can end the call, so a call refused at once (busy, unavailable) fires callStarted and then callEnded. FaceTime calls do not raise the call events.

AddEventHandler('nx_phone:server:callStarted', function(c)
    -- c.callId
    -- c.from       the caller's number
    -- c.to         the number dialled
    -- c.hidden     true when the caller hides their ID
    -- c.service    the service number, for a Config.Calls.Services line
    -- c.hotline    true for a call to a hotline
    -- c.video      always false
end)

nx_phone:server:callAnswered

The same fields as callStarted, plus answeredBy, the number that answered.

nx_phone:server:callEnded

The same fields as callStarted, plus:

  • reason: why it ended, for example hangup, declined, no_answer, busy, unavailable or dropped.
  • answered: whether anyone picked up.
  • durationS: seconds from answer to end, for answered calls.
AddEventHandler('nx_phone:server:callEnded', function(c)
    if c.answered then
        print(('call %s lasted %ds'):format(c.callId, c.durationS or 0))
    end
end)

nx_phone:server:emergencyCall

Someone dialled a service line marked emergency = true. Use it to create a dispatch alert in your own system.

AddEventHandler('nx_phone:server:emergencyCall', function(e)
    -- e.source        the caller's server id
    -- e.callerNumber  nil when they called without a SIM
    -- e.service       the number dialled, for example '911'
    -- e.serviceLabel  for example 'Emergency'
    -- e.coords        vector3 of the caller, when known
    -- e.callId
end)

nx_phone:server:robocallPressed

A robocall victim pressed 1 and is being connected to the campaign's number.

AddEventHandler('nx_phone:server:robocallPressed', function(r)
    -- r.campaignId, r.ownerIdentifier
    -- r.victimSrc, r.victimNumber, r.digit
end)

nx_phone:server:jobSwitched

A player switched their worked job in Shift. The arguments are positional.

AddEventHandler('nx_phone:server:jobSwitched', function(src, newJob, oldJob)
    -- oldJob is nil when they had no job before
end)

nx_phone:companyOpenChanged

A company in the Companies app opened or closed. Use it to light a sign or move a map blip. It also fires for every company that is open when nx_phone starts, including alwaysOpen ones, and with open = false when an open company leaves the directory.

AddEventHandler('nx_phone:companyOpenChanged', function(c)
    -- c.id     the company id: its job name, or the id of a place without a job
    -- c.job    nil for a place without a job
    -- c.label  the name shown in the app
    -- c.open   true when it opened, false when it closed
    SetShopSign(c.id, c.open)   -- your own function
end)

To read the state when your own resource starts, call GetOpenCompanies.

nx_phone:taptopay:paid

A Tap to Pay charge was paid.

AddEventHandler('nx_phone:taptopay:paid', function(p)
    -- p.chargeKey, p.job, p.amount, p.total, p.refId
    -- p.payerSource, p.merchantSource
end)

nx_phone:taptopay:refunded

A paid charge was refunded. The same fields as paid, plus refunded (the amount returned) and partial (true when only part of it could be returned). payerSource is nil when the payer is offline.

Live Activity events

An activity's owner hears about taps and endings through these events. Activities started from a server script raise them on the server, with source set to the player. Activities started from a client script raise them on that client, without source.

-- The player tapped one of the activity's actions.
AddEventHandler('nx_phone:liveActivity:action', function(e)
    -- e.id, e.action (the action's id), e.owner, e.source
end)

-- The player removed the activity from the lock screen. It is gone.
AddEventHandler('nx_phone:liveActivity:dismissed', function(e)
    -- e.id, e.owner, e.source
end)

-- The activity ended.
AddEventHandler('nx_phone:liveActivity:ended', function(e)
    -- e.id, e.owner, e.source
    -- e.reason: 'ended', 'expired', 'owner_stopped' or 'dropped' (the player left)
end)

Check e.owner against your resource name if more than one of your scripts uses Live Activities.

Events you can trigger

nx_phone:notify

A server-side event alternative to the Notify export, for resources that prefer events. It takes the same table. It does not return the notification id, and it ignores anything sent from a client.

TriggerEvent('nx_phone:notify', {
    source = playerId,
    appId = 'x.my_shop.orders',
    title = 'Order ready',
    message = 'Pick it up at the counter.',
})
NX Docs