Skip to main content
An interaction is Zend’s record of a shared activity. You define its states and allowed moves in the manifest; Zend stores it, enforces the moves, notifies participants, and redraws its cards when it changes.
The client SDK returns participants in camelCase. The server API and webhooks use snake_case (app_user_id) and also include money_ref, chat_message_id, expires_at, created_at and updated_at.

How your page gets one

Read zend.launch once on load:

Create

Your server can create interactions too, on behalf of a user who has connected your app. See createInteraction.

Update

  • state is the current state, or one your manifest allows from it. Otherwise INVALID_TRANSITION.
  • data is shallow-merged into the existing data. The total stays under 4 KB.
  • idempotencyKey is required, up to 100 characters. Repeating a key returns the current interaction and changes nothing. Use one key per logical action.
  • expectedVersion is optional. If someone else updated first, the call fails with VERSION_CONFLICT; re-read and retry.
  • Terminal interactions can’t change (INTERACTION_FINISHED).

Who can update

Participants can update from their page. Your server can update any of your app’s interactions with your app key. Moves marked serverOnly in the manifest are refused from a page with TRANSITION_SERVER_ONLY and accepted only from your server:
server.ts
For any game with money or a prize, let your server decide the result.

Expiry

At expires_at, Zend moves unfinished interactions to expired if the type declares an expired state. Otherwise the deadline is cleared and nothing happens. After the deadline, the only allowed update is to expired.

Visibility

Realtime and webhooks

Every change sends an event to each participant’s Zend client, so cards redraw on their own. Your server receives interaction.created and interaction.updated webhooks. Webhooks can arrive out of order; use version to ignore stale ones. For messages between players during a game, use a live room instead of updating the interaction on every move. https://app.usezend.app/i/<id> opens your app at /?interaction=<id> for anyone allowed to see it, after sign-in if needed.