Getting Started
Three calls and you are reading live data: get a token, find the plugin instance, call the module. This page is those three, with code you can paste.
1. Base URL
The API lives on your eConnect server, under /api/v2.
| Deployment | Base URL |
|---|---|
| On-premise | https://<your-server>/api/v2 |
| Cloud | https://<customer>.econnectcloud.com/api/v2 |
Every path in this guide is appended to that. All traffic is HTTPS; the server will not accept tokens over plain HTTP.
The server publishes an OpenAPI 3.0 document covering all 688 endpoints. On a development build it
is at /swagger/v2/swagger.json, with Swagger UI at /swagger. Point openapi-generator,
NSwag or kiota at it and you get a typed client for nothing.
Swagger is not served on production builds. Take the document from a development or staging server, or ask eConnect for the schema that matches your version.
2. Get a token
POST /api/v2/auth/login exchanges a username and password for a token pair.
curl -X POST https://your-server/api/v2/auth/login \
-H 'Content-Type: application/json' \
-d '{ "userName": "integration-svc", "password": "••••••••" }'
{
"accessToken": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "9f2c1e8a4b7d...",
"expiresInSeconds": 900
}
The access token is a compact ES256 JWT with a ~15 minute life. Send it on every other call:
Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
The refresh token is opaque, rotates on each use, and is bound to the session behind it.
Give the integration its own eConnect user with only the permission keys it needs. A token carries that user's rights, so a service account is how you bound what an integration can reach — and it survives the person who set it up leaving.
Signing in with an access id
Unattended integrations can use a static access id instead of a password:
curl -X POST https://your-server/api/v2/auth/login/access-id \
-H 'Content-Type: application/json' \
-d '{ "accessId": "3b7f5c2e-9a41-4d8b-bb0e-7c1a2d3e4f50" }'
The access id is a credential: treat it exactly as you would a password.
Refreshing
When the access token expires, exchange the refresh token for a new pair. Do not re-run login on a
timer — that creates a session every time.
curl -X POST https://your-server/api/v2/auth/token/refresh \
-H 'Content-Type: application/json' \
-d '{ "refreshToken": "9f2c1e8a4b7d..." }'
A refresh token can be used once: the response carries the next one. If a refresh is rejected, sign in again.
| Endpoint | Purpose |
|---|---|
POST /auth/login | Username and password for a token pair |
POST /auth/login/access-id | Static access id for a token pair |
POST /auth/token/refresh | Rotate the refresh token for a new pair |
POST /auth/logout | End the session behind the bearer token |
PUT /auth/session/group | Switch the session's user group; returns a fresh pair |
GET /.well-known/econnect/jwks.json | Public keys, to verify tokens yourself |
3. Find the plugin instance
Most endpoints belong to a plugin instance rather than to the server. List what this deployment has:
curl https://your-server/api/v2/portal/installed-plugins \
-H "Authorization: Bearer $ACCESS_TOKEN"
[
{
"pluginInstalledID": "8f6a1c54-0e2b-4a8e-9f10-2d3c4b5a6e70",
"name": "Casino – Main Floor",
"pluginID": "CASINOCONNECT",
"userGroupID": "1c0de2a4-f8b9-4e2a-9b77-d3f1b6a05c4e"
},
{
"pluginInstalledID": "722939ea-86af-486e-a3f7-ec0e0c4ddf6b",
"name": "Point of Sale",
"pluginID": "POSDATAEVENTS"
}
]
You only see the instances your user is permitted to see. Match on pluginID for the module type
and keep pluginInstalledID — it goes in the path of every call to that module.
Instance ids differ per deployment, and a customer can add a second instance at any time. Look them up at start-up and cache them for the life of the process.
4. Call the module
Now the real work. Reading the most recent point-of-sale events:
curl "https://your-server/api/v2/pos/plugins/722939ea-86af-486e-a3f7-ec0e0c4ddf6b/events?recordsPerPage=50&orderBy=DataTimeStamp%20desc" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Pushing a TITO ticket into the casino module:
curl -X POST https://your-server/api/v2/casino-connect/plugins/8f6a1c54-0e2b-4a8e-9f10-2d3c4b5a6e70/tito-tickets \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"ticketBarcode": "TKT-00412887",
"ticketAmount": 125.50,
"dataTimeStamp": "2026-10-02T21:14:05Z",
"deviceId": "EGM-1042",
"transactionTypeDesc": "Redeem"
}'
The whole thing, in one file
const BASE = 'https://your-server/api/v2';
async function signIn(userName, password) {
const res = await fetch(`${BASE}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userName, password }),
});
if (!res.ok) throw new Error(`sign-in failed: ${res.status}`);
return res.json(); // { accessToken, refreshToken, expiresInSeconds }
}
async function findPlugin(token, pluginId) {
const res = await fetch(`${BASE}/portal/installed-plugins`, {
headers: { Authorization: `Bearer ${token}` },
});
const plugins = await res.json();
const match = plugins.find((p) => p.pluginID === pluginId);
if (!match) throw new Error(`${pluginId} is not installed on this server`);
return match.pluginInstalledID;
}
async function pushTicket(token, instanceId, ticket) {
const res = await fetch(`${BASE}/casino-connect/plugins/${instanceId}/tito-tickets`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify(ticket),
});
if (!res.ok) throw new Error(await res.text()); // ProblemDetails JSON
return res.json();
}
const { accessToken } = await signIn('integration-svc', process.env.EC_PASSWORD);
const casino = await findPlugin(accessToken, 'CASINOCONNECT');
await pushTicket(accessToken, casino, {
ticketBarcode: 'TKT-00412887',
ticketAmount: 125.5,
dataTimeStamp: new Date().toISOString(),
deviceId: 'EGM-1042',
transactionTypeDesc: 'Redeem',
});
using System.Net.Http.Json;
var http = new HttpClient { BaseAddress = new Uri("https://your-server/api/v2/") };
var tokens = await http.PostAsJsonAsync("auth/login", new { userName = "integration-svc", password = pw })
.Result.Content.ReadFromJsonAsync<TokenPair>();
http.DefaultRequestHeaders.Authorization = new("Bearer", tokens!.AccessToken);
var plugins = await http.GetFromJsonAsync<List<PluginInstalled>>("portal/installed-plugins");
var casino = plugins!.First(p => p.PluginID == "CASINOCONNECT").PluginInstalledID;
var response = await http.PostAsJsonAsync($"casino-connect/plugins/{casino}/tito-tickets", new
{
ticketBarcode = "TKT-00412887",
ticketAmount = 125.50m,
dataTimeStamp = DateTime.UtcNow,
deviceId = "EGM-1042",
transactionTypeDesc = "Redeem",
});
response.EnsureSuccessStatusCode();
record TokenPair(string AccessToken, string RefreshToken, int ExpiresInSeconds);
record PluginInstalled(Guid PluginInstalledID, string Name, string PluginID);
Next
- Architecture — what the token carries, how permissions are enforced, how errors and paging work.
- Pushing Data In — ingress per module.
- API Reference — all 688 endpoints.