> ## Documentation Index
> Fetch the complete documentation index at: https://docs.authsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket

> Real-time QR code challenge management via WebSocket connections

## Connection

Connect to the WebSocket endpoint for the region of your Tenant.

| Region        | API URL                                          |
| ------------- | ------------------------------------------------ |
| US (Oregon)   | `wss://api-ws.authsignal.com/ws-v1-challenge`    |
| AU (Sydney)   | `wss://au.api-ws.authsignal.com/ws-v1-challenge` |
| EU (Ireland)  | `wss://eu.api-ws.authsignal.com/ws-v1-challenge` |
| CA (Montreal) | `wss://ca.api-ws.authsignal.com/ws-v1-challenge` |

## Authentication

To authenticate with the WebSocket API, include the required values in the `Sec-WebSocket-Protocol` header:

1. `authsignal-ws` - identifies the Authsignal WebSocket sub-protocol.
2. Exactly one of the following, depending on the type of challenge you are creating:
   * `x.authsignal.tenant.<your-tenant-id>` - use when the challenge is **anonymous** (user is not known yet).
   * `x.authsignal.token.<token-from-track>` - use when the challenge is for a **known user**; supply the token returned by the [track](/api-reference/server-api/track-action) request.

## Message Flow

The WebSocket communication follows this pattern:

1. **Client connects** to the WebSocket endpoint
2. **Client sends** `CREATE_CHALLENGE` message to initiate a challenge
3. **Server responds** with `CHALLENGE_CREATED` confirmation
4. **Server sends** `STATE_CHANGE` messages as the challenge progresses through states

## Challenge States

Challenges progress through the following states:

* `unclaimed` - Challenge created but not yet claimed by a user (This state will not be included in the state change messages)
* `claimed` - User has claimed the challenge on their device
* `approved` - User has approved the challenge
* `rejected` - User has rejected the challenge

## Example

```javascript theme={null}
// Connect to WebSocket
const ws = new WebSocket("wss://api-ws.authsignal.com/ws-v1-challenge", [
  "authsignal-ws",
  "x.authsignal.tenant.5e1eebc0-31c5-42db-b86f-3981f0081ac6",
]);

// Send challenge creation request
ws.send(
  JSON.stringify({
    type: "CREATE_CHALLENGE",
    data: {
      challengeType: "QR_CODE",
      actionCode: "kiosk-login",
    },
  })
);

// Listen for responses
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);

  switch (message.type) {
    case "CHALLENGE_CREATED":
      console.log("Challenge created:", message.data.challengeId);
      break;

    case "STATE_CHANGE":
      console.log("State changed:", message.data.state);
      if (message.data.state === "approved" && message.data.accessToken) {
        console.log("Access token:", message.data.accessToken);
        // Validate the token in your backend
      }
      break;
  }
};
```


## AsyncAPI

````yaml challenge-websocket.json ws-v1-challenge
id: ws-v1-challenge
title: Ws-v1-challenge
description: >-
  Challenge management channel for real-time challenge creation and state
  updates
servers:
  - id: production-us
    protocol: wss
    host: api-ws.authsignal.com
    bindings: []
    variables: []
  - id: production-au
    protocol: wss
    host: au.api-ws.authsignal.com
    bindings: []
    variables: []
  - id: production-eu
    protocol: wss
    host: eu.api-ws.authsignal.com
    bindings: []
    variables: []
  - id: production-ca
    protocol: wss
    host: ca.api-ws.authsignal.com
    bindings: []
    variables: []
address: /ws-v1-challenge
parameters: []
bindings: []
operations:
  - &ref_1
    id: sendCreateChallenge
    title: Send create challenge
    description: Create a new challenge
    type: receive
    messages:
      - &ref_4
        id: createChallenge
        payload:
          - name: Create Challenge
            description: Message to initiate a new challenge
            type: object
            properties:
              - name: type
                type: string
                description: Message type identifier
                enumValues:
                  - CREATE_CHALLENGE
                required: true
              - name: data
                type: object
                required: true
                properties:
                  - name: challengeType
                    type: string
                    description: Type of challenge to create
                    enumValues:
                      - QR_CODE
                    required: true
                  - name: actionCode
                    type: string
                    description: Action code associated with the challenge
                    required: true
                  - name: custom
                    type: object
                    description: Custom data associated with the challenge
                    required: false
        headers: []
        jsonPayloadSchema:
          type: object
          description: Payload for creating a new challenge
          properties:
            type:
              type: string
              enum:
                - CREATE_CHALLENGE
              description: Message type identifier
              x-parser-schema-id: <anonymous-schema-1>
            data:
              type: object
              properties:
                challengeType:
                  type: string
                  enum:
                    - QR_CODE
                  description: Type of challenge to create
                  x-parser-schema-id: <anonymous-schema-3>
                actionCode:
                  type: string
                  description: Action code associated with the challenge
                  example: payment-qr-code
                  x-parser-schema-id: <anonymous-schema-4>
                custom:
                  type: object
                  description: Custom data associated with the challenge
                  additionalProperties: true
                  x-parser-schema-id: <anonymous-schema-5>
              required:
                - challengeType
                - actionCode
              x-parser-schema-id: <anonymous-schema-2>
          required:
            - type
            - data
          x-parser-schema-id: CreateChallengePayload
        title: Create Challenge
        description: Message to initiate a new challenge
        example: |-
          {
            "type": "CREATE_CHALLENGE",
            "data": {
              "challengeType": "QR_CODE",
              "actionCode": "payment-qr-code",
              "custom": {
                "amount": 2499.99,
                "currency": "USD"
              }
            }
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: createChallenge
    bindings: []
    extensions: &ref_0
      - id: x-parser-unique-object-id
        value: ws-v1-challenge
  - &ref_2
    id: receiveChallengeCreated
    title: Receive challenge created
    description: Receive challenge creation confirmation
    type: send
    messages:
      - &ref_5
        id: challengeCreated
        payload:
          - name: Challenge Created
            description: Confirmation of challenge creation
            type: object
            properties:
              - name: type
                type: string
                description: Message type identifier
                enumValues:
                  - CHALLENGE_CREATED
                required: true
              - name: data
                type: object
                required: true
                properties:
                  - name: challengeId
                    type: string
                    description: Unique identifier for the created challenge
                    required: true
                  - name: challengeType
                    type: string
                    description: Type of challenge that was created
                    enumValues:
                      - QR_CODE
                    required: true
                  - name: expiresAt
                    type: string
                    description: ISO 8601 timestamp when the challenge expires
                    required: true
                  - name: state
                    type: string
                    description: Initial state of the challenge
                    enumValues:
                      - unclaimed
                    required: true
        headers: []
        jsonPayloadSchema:
          type: object
          description: Payload confirming challenge creation
          properties:
            type:
              type: string
              enum:
                - CHALLENGE_CREATED
              description: Message type identifier
              x-parser-schema-id: <anonymous-schema-6>
            data:
              type: object
              properties:
                challengeId:
                  type: string
                  description: Unique identifier for the created challenge
                  example: gxl9j7
                  x-parser-schema-id: <anonymous-schema-8>
                challengeType:
                  type: string
                  enum:
                    - QR_CODE
                  description: Type of challenge that was created
                  x-parser-schema-id: <anonymous-schema-9>
                expiresAt:
                  type: string
                  format: date-time
                  description: ISO 8601 timestamp when the challenge expires
                  example: '2025-07-09T03:53:16.000Z'
                  x-parser-schema-id: <anonymous-schema-10>
                state:
                  type: string
                  enum:
                    - unclaimed
                  description: Initial state of the challenge
                  x-parser-schema-id: <anonymous-schema-11>
              required:
                - challengeId
                - challengeType
                - expiresAt
                - state
              x-parser-schema-id: <anonymous-schema-7>
          required:
            - type
            - data
          x-parser-schema-id: ChallengeCreatedPayload
        title: Challenge Created
        description: Confirmation of challenge creation
        example: |-
          {
            "type": "CHALLENGE_CREATED",
            "data": {
              "challengeId": "gxl9j7",
              "challengeType": "QR_CODE",
              "expiresAt": "2025-07-09T03:53:16.000Z",
              "state": "unclaimed"
            }
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: challengeCreated
    bindings: []
    extensions: *ref_0
  - &ref_3
    id: receiveStateChange
    title: Receive state change
    description: Receive challenge state updates
    type: send
    messages:
      - &ref_6
        id: stateChange
        payload:
          - name: State Change
            description: Challenge state update
            type: object
            properties:
              - name: type
                type: string
                description: Message type identifier
                enumValues:
                  - STATE_CHANGE
                required: true
              - name: data
                type: object
                required: true
                properties:
                  - name: challengeId
                    type: string
                    description: Unique identifier for the challenge
                    required: true
                  - name: state
                    type: string
                    description: New state of the challenge
                    enumValues:
                      - claimed
                      - approved
                      - rejected
                    required: true
                  - name: accessToken
                    type: string
                    description: >-
                      JWT access token provided when challenge is approved. Only
                      present for approved state.
                    required: false
        headers: []
        jsonPayloadSchema:
          type: object
          description: Payload for challenge state updates
          properties:
            type:
              type: string
              enum:
                - STATE_CHANGE
              description: Message type identifier
              x-parser-schema-id: <anonymous-schema-12>
            data:
              type: object
              properties:
                challengeId:
                  type: string
                  description: Unique identifier for the challenge
                  example: gxl9j7
                  x-parser-schema-id: <anonymous-schema-14>
                state:
                  type: string
                  enum:
                    - claimed
                    - approved
                    - rejected
                  description: New state of the challenge
                  x-parser-schema-id: <anonymous-schema-15>
                accessToken:
                  type: string
                  description: >-
                    JWT access token provided when challenge is approved. Only
                    present for approved state.
                  example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                  x-parser-schema-id: <anonymous-schema-16>
              required:
                - challengeId
                - state
              x-parser-schema-id: <anonymous-schema-13>
          required:
            - type
            - data
          x-parser-schema-id: StateChangePayload
        title: State Change
        description: Challenge state update
        example: |-
          {
            "type": "STATE_CHANGE",
            "data": {
              "challengeId": "gxl9j7",
              "state": "claimed"
            }
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: stateChange
    bindings: []
    extensions: *ref_0
sendOperations:
  - *ref_1
receiveOperations:
  - *ref_2
  - *ref_3
sendMessages:
  - *ref_4
receiveMessages:
  - *ref_5
  - *ref_6
extensions:
  - id: x-parser-unique-object-id
    value: ws-v1-challenge
securitySchemes: []

````