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.
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.
Session cookie — critical
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
- List queues:
GET /rest/servicepoint/branches/{branchId}/queues- Do not transfer to queues with
queueType: "APPOINTMENT_QUEUE".
- Do not transfer to queues with
- Transfer:
PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/transfer/queues/{queueId}
Transfer to a service point pool
- List pools:
GET /rest/servicepoint/branches/{branchId}/servicePoints/pools - Optionally inspect pool contents:
GET /rest/servicepoint/branches/{branchId}/servicePoints/pools/{poolId}/visits - Transfer:
PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/transfer/servicepointPool/{servicepointPoolId} - 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.
- List users:
GET /rest/servicepoint/branches/{branchId}/users - Optionally inspect user pool:
GET /rest/servicepoint/branches/{branchId}/users/{userId}/visits - Transfer:
PUT /rest/servicepoint/branches/{branchId}/visits/{visitId}/transfer/userPool/{userId} - 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:
- Get available services:
GET /rest/servicepoint/branches/{branchId}/services - 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.).
| Operation | Endpoint | Effect |
|---|---|---|
| Recall | PUT .../visits/{visitId}/recall | Re-announces the ticket number at the counter display |
| Recycle | PUT .../visits/{visitId}/recycle | Returns the visit to the queue (e.g. customer stepped away) |
| No-show | PUT .../visits/{visitId}/noshow | Marks 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:
| Header | Example value |
|---|---|
ERROR_CODE | 8054 |
ERROR_MESSAGE | 8054: The visit with id 5 does not belong to the user johndoe |
Common error codes:
| Code | Meaning |
|---|---|
8013 | Service does not exist for the given branch |
8048 | Work profile does not exist for the given branch |
8054 | Visit does not belong to the authenticated user |
8056 | User 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
Related pages
- Customize Applications overview — other customization patterns
- API Gateway guide — recommended for routing public API calls; Counter API should not be proxied through API Gateway to untrusted client