Skip to content

Clients ​

Each client is a thin library over the API: one call per operation, with the same names in every language. None of them draws any UI. Your product shows its own Report a problem screen and calls the library.

TypeScriptthe browser and Node, typed
Godot 4an addon in GDScript, on native builds and on the web
C#/.NET (Unity), Swift, Kotlin, Unrealplanned

Every client:

  • asks the service for the user's identity the first time it's needed, and keeps it;
  • sends reports with a screenshot, adding your product's context and telemetry from callbacks;
  • watches for answers, over a stream where it can and by polling otherwise, and tells you about each answer once;
  • gives and withdraws the user's contact;
  • makes and claims transfer codes;
  • gets the user's copy of their data, and erases it.

TypeScript ​

ts
import { AliasClient, LocalStorageIdentityStore } from 'alias-support'

const alias = new AliasClient({
  url: 'https://support.example.com',
  key: PRODUCT_KEY,
  appVersion: '1.4.2',
  store: new LocalStorageIdentityStore(),   // keep the identity between visits
  context: () => ({ level: game.level }),
  telemetry: () => ({ fps: game.fps }),
})

const ticket = await alias.report({ note: "The door won't open", screenshot: await canvasJpeg() })

const stop = alias.watch((u) => toast(`Support answered #${u.ticket}`))
  • Calls: getProduct, identity, me, report, tickets, ticket, reply, updates, watch, getContact, setContact, withdrawContact, newTransfer, claimTransfer, useIdentity, myData, eraseMe, forget.
  • Errors are thrown as AliasError, carrying the status and the service's reason: a telemetry schema mismatch says which field.
  • Screenshots can be bytes, a Blob or base64.
  • Identity stores: in memory, localStorage, or your own (load, save).

Godot ​

gdscript
var alias := AliasSupport.new()
alias.url = "https://support.example.com"
alias.key = PRODUCT_KEY
alias.app_version = ProjectSettings.get_setting("application/config/version")
alias.context_provider = func() -> Dictionary: return {"level": level_name}
alias.telemetry_provider = func() -> Dictionary: return {"fps": Engine.get_frames_per_second()}
add_child(alias)

var r: Dictionary = await alias.report("The door won't open", get_viewport().get_texture().get_image())
if not r.ok:
	show_error(r.error)

alias.answered.connect(func(u: Dictionary): notify("Support answered #%d" % u.ticket))
alias.watch()
  • Calls: the same as the TypeScript client's, in snake_case (get_product, report, claim_transfer…). Each is a coroutine returning {ok, status, data, error}.
  • Screenshots can be an Image (sent as a JPEG) or JPEG bytes.
  • The identity is kept in user://, under a name of your choice, so one game can talk to several products. It's never made on the device: the service makes it from a secure random source, whatever the platform has.
  • Answers: native builds keep a stream open and also poll. Web builds poll only.
  • Signals: answered and identity_changed.