Skip to main content

Custom Counter Integration

The Orchestra Counter API (/rest/servicepoint/...) lets you build custom staff workstation interfaces — replacing or extending the default Orchestra terminal with your own UI. It covers the full agent lifecycle: starting a session, calling and serving visits, handling transfers, and closing out.

License requirement

Exposing the internal Counter API may require a license and/or additional Orchestra components. Contact Qmatic before building on this API in production.


Authentication​

Every request requires HTTP Basic Auth (Authorization: Basic <base64(user:password)>). Use the same credentials the staff member would use to log in to Orchestra.

The first request to any /rest/servicepoint/ endpoint creates a server-side session and returns a Set-Cookie header. You must capture this cookie and send it with every subsequent request. Failing to do so creates a new server session on each call, which:

  • inflates user statistics
  • can degrade server performance under load

Store the cookie in your HTTP client and attach it automatically to all requests in the session. Most HTTP libraries handle this with a cookie jar or session object.


Basic staff flow​

A complete agent shift follows this lifecycle:

Step-by-step endpoints​

1. Get branches + session cookie

GET /rest/servicepoint/branches
Authorization: Basic <credentials>

Returns the branches the authenticated user has access to. Capture the Set-Cookie from the response.

[{ "id": 1, "name": "Branch 1" }]

2. Start user session

PUT /rest/servicepoint/branches/{branchId}/users/{userName}

Creates a user session on the selected branch. userState will be NO_STARTED_SERVICE_POINT_SESSION.

3. List service points

GET /rest/servicepoint/branches/{branchId}/servicePoints/deviceTypes/SW_SERVICE_POINT

Returns service points of type SW_SERVICE_POINT (software terminals). Let the agent choose one.

4. List work profiles

GET /rest/servicepoint/branches/{branchId}/workProfiles

Returns available work profiles (each defines which queues the agent will call from).

5. Connect agent to service point

PUT /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/users/{userName}

Opens a service point session. servicePointState changes to OPEN.

6. Set work profile

PUT /rest/servicepoint/branches/{branchId}/users/{userName}/workProfile/{workProfileId}

Completes setup. userState is now INACTIVE — the agent is ready to call.

7. Call next visit

POST /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/visits/next

Calls the next waiting ticket from the queues in the active work profile. userState changes to SERVING. The response includes the full visit object with ticketId, waiting time, service details, and allowed actions (recallAllowed, recycleAllowed, noshowAllowed).

8. End visit

PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/end

Closes the transaction. userState returns to INACTIVE.

9. Close service point session

DELETE /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/users/{userName}

Ends the service point session. servicePointState changes to CLOSED.

10. Logout

PUT /rest/servicepoint/logout;force=false;timeout=false

Destroys the user session entirely. Use force=true to log out even if the agent is mid-visit. Use timeout=true to record the session outcome as TERMINAL_TIMEOUT in statistics.


Calling a specific visit by ID​

To call a particular visit (e.g. when a customer returns or the agent needs to recall a specific ticket):

GET /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/visits/{visitId}

This bypasses queue order and calls the named visit directly.


Transfers​

When a visit needs to be redirected, three transfer mechanisms are available. All require an active SERVING state.

Transfer to a queue​

  1. List queues: GET /rest/servicepoint/branches/{branchId}/queues
    • Do not transfer to queues with queueType: "APPOINTMENT_QUEUE".
  2. Transfer: PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/transfer/queues/{queueId}

Transfer to a service point pool​

  1. List pools: GET /rest/servicepoint/branches/{branchId}/servicePoints/pools
  2. Optionally inspect pool contents: GET /rest/servicepoint/branches/{branchId}/servicePoints/pools/{poolId}/visits
  3. Transfer: PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/transfer/servicepointPool/{servicepointPoolId}
  4. Call from pool: GET /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/visits/servicepointPool/{servicepointPoolId}

Transfer to a user pool​

Use when you want a specific agent to handle the visit.

  1. List users: GET /rest/servicepoint/branches/{branchId}/users
  2. Optionally inspect user pool: GET /rest/servicepoint/branches/{branchId}/users/{userId}/visits
  3. Transfer: PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/transfer/userPool/{userId}
  4. Call from pool: GET /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/visits/userPool/{userId}

Walk-direct tickets​

Create an on-the-spot ticket for a customer who arrives without a queue ticket:

  1. Get available services: GET /rest/servicepoint/branches/{branchId}/services
  2. Create the walkdirect:
POST /rest/servicepoint/branches/{branchId}/servicePoints/{servicePointId}/walkDirects
Content-Type: application/json

{ "serviceId": 2 }

The response includes a full visit object — the agent is immediately placed in SERVING state.


Multi-service visits​

When a single visit covers multiple services in sequence (e.g. document check followed by payment):

Add a service to the current visit:

POST /rest/servicepoint/branches/{branchId}/visits/{visitId}/services/{serviceId}

Serve a specific service from the visit:

PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/services/{visitServiceId}/serve

The visitServiceId is returned in the unservedVisitServices array of the visit object.


Optional operations​

These can be performed on an active visit when the visit object indicates they are allowed (recallAllowed, etc.).

OperationEndpointEffect
RecallPUT .../visits/{visitId}/recallRe-announces the ticket number at the counter display
RecyclePUT .../visits/{visitId}/recycleReturns the visit to the queue (e.g. customer stepped away)
No-showPUT .../visits/{visitId}/noshowMarks the visit as a no-show and closes it

Visit parameters​

Read or write arbitrary key-value data on a visit (e.g. case reference, order number):

PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/parameters/
Content-Type: application/json

{ "orderNumber": "123456AB" }

Parameters are merged — existing keys are updated, new keys are added. Parameters cannot be deleted.

Queue inspection​

Show agents how many customers are waiting across queues:

# Queues for a specific work profile
GET /rest/servicepoint/branches/{branchId}/workProfiles/{workProfileId}/queues

# All visits in a queue (full visit object)
GET /rest/servicepoint/branches/{branchId}/queues/{queueId}/visits/full

# All visits in a queue (lightweight — ticket ID, wait time, queue ID)
GET /rest/servicepoint/branches/{branchId}/queues/{queueId}/visits

Error handling​

Errors are returned in the response headers, not the body:

HeaderExample value
ERROR_CODE8054
ERROR_MESSAGE8054: The visit with id 5 does not belong to the user johndoe

Common error codes:

CodeMeaning
8013Service does not exist for the given branch
8048Work profile does not exist for the given branch
8054Visit does not belong to the authenticated user
8056User is not active on a service point

Response structure​

Most endpoints return a state object that reflects the current agent context:

{
"branchId": 1,
"userState": "SERVING",
"visitState": "OK",
"servicePointId": 8,
"servicePointName": "Terminal 2",
"servicePointState": "OPEN",
"visit": { ... },
"workProfileId": 4,
"workProfileName": "All queues",
"servicePointDeviceTypes": ["SW_SERVICE_POINT"]
}

userState lifecycle: NO_STARTED_USER_SESSION → NO_STARTED_SERVICE_POINT_SESSION → NO_PROFILE_SET → INACTIVE → SERVING → INACTIVE (loop) → NO_STARTED_SERVICE_POINT_SESSION → NO_STARTED_USER_SESSION