Developer API
Blixt exposes a public export surface for other FiveM resources. Use it when a script wants the phone to do something a real handset could do: notify a player, open an app, send mail, add a map marker, create a calendar item, check duty, or request a Gov ID grant.
This page covers the production integration contract. For app registration and launcher metadata, also see External apps.
Trust model
Section titled “Trust model”Most server exports are gated by blixt:trusted_resources.
set blixt:trusted_resources "dispatch,jobs,blixt-racing"Same-resource calls from Blixt always pass. External resources must be in the
allowlist unless an export documents a narrower exception. RegisterExternalApp
is the only public handshake that is not gated; it only registers launcher
metadata and does not grant privileged data access.
Client exports run on a player’s client and are not allowlist-gated. Use client exports for local presentation and native-client actions. Use server exports for database-backed or cross-player work.
Calling exports
Section titled “Calling exports”Lua server:
local ok = exports.blixt:CreateNotification(source, { appId = 'jobs', appName = 'Jobs', title = 'Shift starting', content = 'You are on the clock.', priority = 'normal',})TypeScript server:
const blixt = (global as any).exports.blixt;
const result = await blixt.CreateCalendarReminder(source, { title: 'Impound check', dueAt: Date.now() + 30 * 60_000, reminderPreset: '15m',});Lua client:
exports.blixt:OpenMapLocation(-215.4, -1320.1, 'Mechanic shop')Result shapes
Section titled “Result shapes”Newer data-backed exports return:
{ ok: true, data: unknown }{ ok: false, error: string }Some older compatibility exports return boolean, number | null, or a
domain-specific result. Those shapes are listed below.
Server exports
Section titled “Server exports”Phone and app control
Section titled “Phone and app control”| Export | Returns | Notes |
|---|---|---|
GetPhoneNumber(source) | Promise<string/null> | Resolves through player cache / framework record. |
getPlayerPhoneNumber(source) | string/null | Fast cache-only lookup. |
GetActiveHandsetId(source, deviceKind?) | Promise<string/null> | deviceKind defaults to phone; use for handset-scoped satellite data. |
OpenPhone(source) | boolean | Opens the phone if the client accepts it. |
ClosePhone(source) | boolean | Closes the phone. |
TogglePhone(source) | boolean | Toggles the phone. |
OpenApp(source, appId, launchPayload?) | boolean | Opens the phone and focuses a registered app. |
setPhoneDisabled(source, disabled) | void | Blocks local phone toggle and closes the phone when disabled. |
setBadge(source, appId, count) | void | Sets an authoritative app badge count. |
OpenApp can target built-in app ids such as messages, mail, maps, and
calendar, or external app ids registered through RegisterExternalApp.
Notifications
Section titled “Notifications”| Export | Returns | Notes |
|---|---|---|
CreateNotification(source, payload) | boolean | Persist and live-deliver to the active route behind a source. |
createNotification(source, payload) | boolean | Lowercase compatibility alias. |
CreateNotificationByPhoneNumber(phoneNumber, payload) | boolean | Persist and deliver by phone number route. |
createNotificationByPhoneNumber(phoneNumber, payload) | boolean | Lowercase compatibility alias. |
CreateNotificationByTarget(target, payload) | boolean | Persist and deliver to a typed notification route. |
Payload:
{ appId: string; appName: string; title: string; content: string; imageUrl?: string; avatarUrl?: string; priority?: 'silent' | 'normal' | 'urgent' | 'call'; intent?: { appId: string; action?: string; params?: Record<string, unknown>; }; actions?: Array<{ id: string; label: string; icon?: string; type?: 'default' | 'reply' | 'destructive'; intent?: { appId: string; action?: string; params?: Record<string, unknown> }; }>; source?: { type: string; id: string }; invalidate?: string[];}Targets for CreateNotificationByTarget:
{ kind: 'phone_number'; id: string }{ kind: 'handset'; id: string }{ kind: 'blixt_session'; id: string }{ kind: 'blixt_account'; id: string }{ kind: 'app_account'; id: string }Use Blixt notifications when the message should appear in phone history and support tap intents. Use framework-native notification exports only for immediate game-screen feedback.
Messages, mail, and bills
Section titled “Messages, mail, and bills”| Export | Returns | Notes |
|---|---|---|
sendMessage(source, targetNumber, content, imageUrl?) | Promise<MessageResult> | Sends a text as the source character. |
SendMail(source, input) | Promise<number/null> | Creates mail for the source character and notifies the live route. |
SendMailByIdentifier(identifier, input) | Promise<number/null> | Creates mail by framework character identifier. |
SendMailByPhoneNumber(phoneNumber, input) | Promise<number/null> | Creates mail by phone route and persists the mail notification. |
CreateBill(source, input) | Promise<number/null> | Creates a bill for the source character. |
CreateBillByPhoneNumber(phoneNumber, input) | Promise<number/null> | Creates a bill by phone route. |
Mail input:
{ sender: string; subject: string; body: string;}Bill input:
{ issuer: string; description?: string; amount: number; dueAt?: number; reference?: string; lineItems?: Array<{ label: string; amount: number }>; payeeIdentifier?: string;}Calendar
Section titled “Calendar”| Export | Returns | Notes |
|---|---|---|
CreateCalendarEvent(source, input) | Promise<Result> | Creates an event in the source’s active handset/session calendar. |
CreateCalendarReminder(source, input) | Promise<Result> | Creates a reminder. Requires dueAt. |
CreateCalendarInvite(source, input) | Promise<Result> | Invites phone-number recipients to a source-owned calendar event. |
Event and reminder input:
{ title: string; notes?: string | null; startsAt?: number | null; endsAt?: number | null; dueAt?: number | null; startDate?: string | null; endDate?: string | null; allDay?: boolean; reminderPreset?: 'none' | 'at_time' | '15m' | '1h' | '1d';}Invite input:
{ eventId: number; recipients: Array<string | { routeKind?: 'phone_number'; routeId: string }>; permissions?: { canInviteOthers?: boolean; canEditTime?: boolean; canEditLocation?: boolean; canSeeGuestList?: boolean; canSeeSourceLink?: boolean; };}Calendar exports go through the same router validation as the app: handset scope, sync enrollment, shared-event rules, and notification delivery are owned by Blixt.
| Export | Returns | Notes |
|---|---|---|
OpenMapLocation(source, x, y, label?, options?) | boolean | Opens the phone Maps app, sets a waypoint by default, and focuses the location. |
SetMapWaypoint(source, x, y) | boolean | Sets a native GTA waypoint on one client. |
ClearMapWaypoint(source) | boolean | Clears the client’s waypoint. |
AddMapBlip(source, id, blip) | boolean | Adds or replaces a dynamic phone-map blip for one player. |
RemoveMapBlip(source, id) | boolean | Removes a dynamic phone-map blip for one player. |
AddMapBlipForAll(id, blip) | boolean | Adds or replaces a dynamic phone-map blip for all clients. |
RemoveMapBlipForAll(id) | boolean | Removes a dynamic phone-map blip for all clients. |
CreateMapSavedPlace(source, input) | Promise<Result> | Saves a place into the source character’s Maps app. |
CreateMapIncidentPin(source, input) | Promise<Result> | Creates a job/gang-scoped incident pin after Blixt validates source scope. |
ClearMapIncidentPin(source, id) | Promise<Result> | Clears an incident pin the source can access. |
StartLiveLocationSession(source, input) | Promise<Result> | Starts a Maps live-location request to another phone number. |
Map blip:
{ id?: string; label: string; position: { x: number; y: number } | [number, number]; color?: string; icon?: string;}Open-map options:
{ category?: string; kind?: string; sourcePlaceId?: string; setWaypoint?: boolean; // default true selectedPlace?: boolean; // open details without forcing waypoint intent}Saved-place input:
{ label: string; x: number; y: number; category?: string; note?: string | null; sourceKind?: string; sourcePlaceId?: string | null;}Incident pin input:
{ scopeType?: 'job' | 'gang'; scopeName?: string; source?: string; sourceRef?: string | null; label: string; description?: string | null; x: number; y: number; category?: string; ttlMinutes?: number;}Live-location input:
{ recipientPhoneNumber: string; direction?: 'one-way' | 'mutual'; durationMinutes?: number;}Health
Section titled “Health”| Export | Returns | Notes |
|---|---|---|
recordHealthSnapshot(source, snapshot) | Promise<HealthResult> | Stores a Health snapshot for the current character behind source. |
Business
Section titled “Business”Business exports are trusted-resource only and always resolve the current
character from source.
| Export | Returns |
|---|---|
getBusinessSummary(source) | Promise<Result> |
getBusinessMemberships(source) | Promise<Result> |
IsBusinessOnDuty(source, businessId?) | Promise<boolean> |
VerifyBusinessDuty(source, businessId, expectedHolderIdentifier) | Promise<boolean> |
GetBusinessDutyState(source, businessId?) | Promise<unknown/null> |
SetBusinessDuty(source, businessId, onDuty, reason?) | Promise<boolean> |
HasBusinessPermission(source, businessId, permission) | Promise<boolean> |
getBusinessTreasurySummary(source, businessId) | Promise<Result> |
getBusinessLedger(source, businessId, limit?) | Promise<Result> |
createBusinessDeposit(source, businessId, amount, reason?, idempotencyKey?) | Promise<Result> |
createBusinessWithdrawal(source, businessId, amount, reason?, idempotencyKey?) | Promise<Result> |
createBusinessPaymentRequest(source, input) | Promise<Result> |
claimBusinessPaymentRequest(source, input) | Promise<Result> |
cancelBusinessPaymentRequest(source, input) | Promise<Result> |
getBusinessCardsState(source, businessId) | Promise<Result> |
issueBusinessCard(source, input) | Promise<Result> |
updateBusinessCardPolicy(source, input) | Promise<Result> |
freezeBusinessCard(source, businessId, grantId, reason?) | Promise<Result> |
revokeBusinessCard(source, businessId, grantId, reason?) | Promise<Result> |
seedBusinessConfig(config) | Promise<Result> |
setBusinessFormationConfig(config) | FormationConfigResult |
Gov ID
Section titled “Gov ID”| Export | Returns | Notes |
|---|---|---|
createGovIdChallenge(source, input) | Promise<Result> | Creates a challenge for the current character. |
verifyGovIdGrant(source, input) | Promise<Result> | Verifies a grant for the current character/session. |
invalidateGovIdGrants(source, input?) | Promise<Result> | Invalidates remembered grants for the current character/session. |
External resources do not pass target character identifiers. Blixt resolves
them from source.
External apps
Section titled “External apps”| Export | Returns | Notes |
|---|---|---|
RegisterExternalApp(data) | boolean | Registers launcher metadata for a satellite app. This is discovery only. |
Minimal payload:
{ id: string; resourceName: string; name: string;}Client exports
Section titled “Client exports”Call these from another client resource.
| Export | Returns | Notes |
|---|---|---|
OpenPhone() | boolean | Opens the local phone unless disabled or pause menu is active. |
ClosePhone() | boolean | Closes the local phone. |
TogglePhone() | boolean | Toggles the local phone. |
SetPhoneDisabled(disabled) | void | Local disabled flag. |
IsPhoneOpen() | boolean | Current full-open visibility state. |
IsPhonePeeking() | boolean | Whether the passive phone peek is visible. |
IsPhoneDisabled() | boolean | Local disabled flag. |
GetPhoneState() | string | State-machine state such as closed, peek, opening, open, in_call, or in_camera. |
OpenApp(appId, launchPayload?) | boolean | Opens the phone and focuses a registered app. |
SetBadge(appId, count) | boolean | Sets a local app badge. |
CreatePhoneNotification(payload) | boolean | Creates a local phone notification toast/history entry. Prefer server notifications for persistence. |
AddMapBlip(id, blip) | MapBlip/null | Adds or replaces a local dynamic phone-map blip. |
RemoveMapBlip(id) | void | Removes a local dynamic phone-map blip. |
GetMapBlips() | MapBlip[] | Returns static plus dynamic phone-map blips. |
SetMapWaypoint(x, y) | boolean | Sets native waypoint and updates Maps UI if open. |
ClearMapWaypoint() | void | Clears native waypoint and Maps UI. |
GetMapWaypoint() | MapWaypoint/null | Reads current native waypoint. |
GetPlayerLocation() | PlayerLocation | Reads local player location. |
OpenMapLocation(x, y, label?, options?) | boolean | Opens Maps and focuses a location. |
Recipes
Section titled “Recipes”Notify a phone and open Maps when tapped:
exports.blixt:CreateNotification(source, { appId = 'maps', appName = 'Maps', title = 'Tow request', content = 'A stranded vehicle was reported.', priority = 'normal', intent = { appId = 'maps', params = { x = -215.4, y = -1320.1, label = 'Tow request' }, },})Immediately show a location on the player’s phone:
exports.blixt:OpenMapLocation(source, -215.4, -1320.1, 'Tow request', { category = 'automotive', setWaypoint = true,})Send mail by phone number:
local id = exports.blixt:SendMailByPhoneNumber('555-0142', { sender = 'San Andreas Courts', subject = 'Hearing scheduled', body = 'Your hearing is scheduled for tomorrow at 10:00.',})Create a reminder:
exports.blixt:CreateCalendarReminder(source, { title = 'Court hearing', dueAt = os.time() * 1000 + 24 * 60 * 60 * 1000, reminderPreset = '1h',})Add a temporary map blip for everyone:
exports.blixt:AddMapBlipForAll('event-meetup', { label = 'Meetup', position = { x = -551.2, y = -191.4 }, color = '#3b82f6', icon = 'map-pin',})Privacy rules
Section titled “Privacy rules”- Do not resolve unknown phone numbers to framework character metadata.
- Do not expose inventory, wallet, job, citizen ID, or account metadata through notification previews or map labels.
- Use source-scoped exports when the current character must authorize the work.
- Treat phone-number routes as in-character contact routes, not admin lookup handles.