
AUDS - Arbitrary User Data Store
This API is currently in development and subject to change. Do not use in production.
1. Create userdata
Use the following endpoint to create userdata. The <freeform-key> can be any label you choose to categorize your data (e.g. tests, levels, maps, etc.).
Request body
{
"data": {
"tiles": [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0],
"note": "data in userdata is freeform, can be anything."
},
"values": {
"levelname": "Test level",
"type": "arena-1v1",
"note": "'values' can only be key/value pairs where values can only be string, number, or boolean"
}
}
Example request
const body = {
data: {
tiles: [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0],
note: 'data in userdata is freeform, can be anything.'
},
values: {
levelname: 'Test level',
type: 'arena-1v1',
note: "'values' can only be key/value pairs where values can only be string, number, or boolean"
}
};
const requestOptions = {
method: 'POST',
body: JSON.stringify(body),
};
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests', requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Example response
{
"id": "ce702oq1gkcvlv1tmlgg",
"secret": "Qn8iO6bQVlGyVPkJhoi4oHwufb6GWgpgyedP5cO3fB39rzwTJZwg7N2n7GbLU3aG",
"meta": {
"revision": 1,
"created_at": "2022-12-05T14:34:11.67798351Z",
"expires_at": "2023-12-05T14:34:11.67798351Z",
"expires_in": 31536000
},
"values": {
"levelname": "Test level",
"note": "'values' can only be key/value pairs where values can only be string, number, or boolean",
"type": "arena-1v1"
}
}
Returned secret
The response will include an id and a secret. The secret is never returned again, so make sure you store it if you plan to update this userdata later.
2. Fetch userdata by ID
Use this endpoint to retrieve a previously created userdata entry by its id.
Example request
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests/ce702oq1gkcvlv1tmlgg')
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Example response
{
"id": "ce702oq1gkcvlv1tmlgg",
"meta": {
"revision": 1,
"created_at": "2022-12-05T14:34:11.677983Z",
"expires_at": "2023-12-05T14:37:02.733083Z",
"expires_in": 31536000
},
"values": {
"levelname": "Test level",
"note": "'values' can only be key/value pairs where values can only be string, number, or boolean",
"type": "arena-1v1"
},
"data": {
"note": "data in userdata is freeform, can be anything.",
"tiles": [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0]
}
}
3. Get list of userdata
Use the following endpoint to list userdata. You can optionally filter and sort the results.
GET https://auds.poki.io/v0/<your-poki-game-id>/userdata/<freeform-key>?q=type:arena-1v1&sort=key&includedata
Supported query parameters
| Parameter | Description |
|---|---|
q=key:value |
Filters the results by a values key. Only basic matching is supported right now. This will change. |
q=<json> |
URL-encoded JSON query for advanced filters. Syntax and examples can be found here: https://github.com/poki/mongodb-filter-to-postgres |
sort=key |
Sorts results ascending by the given values key. |
sort=-key |
Sorts results descending by the given values key. |
includedata |
Includes the data field in the returned items. |
limit=n |
Only return n results (min 1, max 100) |
Example request
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests?q=type:arena-1v1')
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Example response
{
"total": 1,
"items": [
{
"id": "ce702oq1gkcvlv1tmlgg",
"meta": {
"revision": 1,
"created_at": "2022-12-05T14:34:11.677983Z",
"expires_at": "2023-12-05T14:34:11.677983Z",
"expires_in": 31536000
},
"values": {
"levelname": "Test level",
"note": "'values' can only be key/value pairs where values can only be string, number, or boolean",
"type": "arena-1v1"
}
}
]
}
4. Update userdata by ID with secret
To update userdata, you must supply the secret you received during creation, or your admin token through the Authorization header. This endpoint will only update keys you provide. Omitted fields remain unchanged.
Request body
{
"secret": "<SECRET_RECEIVED_ON_CREATE>",
"data": {
"tiles": [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1]
},
"values": {
"levelname": "Test level (edited)",
"type": "arena-1v1"
}
}
Example request
const body = {
secret: 'Qn8iO6bQVlGyVPkJhoi4oHwufb6GWgpgyedP5cO3fB39rzwTJZwg7N2n7GbLU3aG',
data: {
tiles: [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1]
},
values: {
levelname: 'Test level (edited)',
type: 'arena-1v1'
}
};
const requestOptions = {
method: 'POST',
body: JSON.stringify(body),
// Or instead of the secret in the body:
// headers: {
// 'Authorization': 'AdminToken <your-admin-token>',
// }
};
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests/ce702oq1gkcvlv1tmlgg', requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Example response
{
"id": "ce702oq1gkcvlv1tmlgg",
"meta": {
"revision": 2,
"created_at": "2022-12-05T14:34:11.677983Z",
"updated_at": "2022-12-05T14:41:58.223397772Z",
"expires_at": "2023-12-05T14:41:58.223397772Z",
"expires_in": 31536000
},
"values": {
"levelname": "Test level (edited)",
"type": "arena-1v1"
}
}
5. Delete userdata by ID with secret
To delete userdata, you must supply the secret you received during creation, or your admin token through the Authorization header.
Request body
Example request
const body = {
secret: 'Qn8iO6bQVlGyVPkJhoi4oHwufb6GWgpgyedP5cO3fB39rzwTJZwg7N2n7GbLU3aG',
};
const requestOptions = {
method: 'DELETE',
body: JSON.stringify(body),
// Or instead of the body:
// headers: {
// 'Authorization': 'AdminToken <your-admin-token>',
// }
};
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests/ce702oq1gkcvlv1tmlgg', requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
6. Increment a counter value
Use this endpoint to increment a numeric counter inside the values object. This is meant for public counters (e.g. play-count) and does not require the secret like the update endpoint does.
POST https://auds.poki.io/v0/<your-poki-game-id>/userdata/<freeform-key>/<id>/_increment?key=<value-key>
Notes
- The
keymust containcount(e.g.play-count,count-score). - The existing value must be a number.
- The counter increases by
1. - The
revisiondoes not change; onlyupdated_atchanges. - No request body is required.
- No
secretorAuthorizationheader is required for this endpoint.
Example request
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests/ce702oq1gkcvlv1tmlgg/_increment?key=play-count', {
method: 'POST'
})
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Example response
{
"id": "ce702oq1gkcvlv1tmlgg",
"meta": {
"revision": 1,
"created_at": "2022-12-05T14:34:11.677983Z",
"updated_at": "2022-12-05T14:41:58.223397772Z",
"expires_at": "2023-12-05T14:41:58.223397772Z",
"expires_in": 31536000
},
"values": {
"levelname": "Test level",
"play-count": 42
}
}
7. Vote on a value
Use this endpoint to increment vote counters (e.g. up-vote, down-vote). Voting is limited to once per IP address, per value key, per day, and does not require the secret like the update endpoint does.
Notes
- The existing value must be a number.
- Voting is tracked by client IP and day; duplicate votes return
409. - The
revisiondoes not change; onlyupdated_atchanges. - No request body is required.
- No
secretorAuthorizationheader is required for this endpoint.
Example request
fetch('https://auds.poki.io/v0/use-your-poki-game-id/userdata/tests/ce702oq1gkcvlv1tmlgg/_vote?key=up-vote', {
method: 'POST'
})
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Example response
{
"id": "ce702oq1gkcvlv1tmlgg",
"meta": {
"revision": 1,
"created_at": "2022-12-05T14:34:11.677983Z",
"updated_at": "2022-12-05T14:41:58.223397772Z",
"expires_at": "2023-12-05T14:41:58.223397772Z",
"expires_in": 31536000
},
"values": {
"levelname": "Test level",
"up-vote": 33
}
}
8. Authentication options
Update and delete endpoints accept three authentication methods:
secretin the request body (the default).Authorization: AdminToken <your-admin-token>header.Authorization: Bearer <poki-for-developers-jwt>header.
For Poki for Developers tokens, role=developer requires the token to include the team that owns the game. role=admin can manage any game. Unauthorized access returns 404 to avoid leaking record existence.
9. CORS and allowed origins
AUDS only allows browser requests from Poki and development domains:
localhost127.0.0.1::1*.netlify.applaunch.playcanvas.complaycanv.as*.scf.usercontent.goog
10. Validation and error responses
Validation rules
<freeform-key>andvalueskeys must match/[a-z][a-z0-9_-]{,31}/i(no double dashes).<id>must match/^[0-9a-v]{20}$/.valuesmay only contain strings, numbers, or booleans (no nested objects).datacan be any JSON type.
Common error responses
400 bad-requestfor invalid JSON payloads.400 invalid-url-paramsfor invalid data type or id.400 invalid-valuesfor invalidvalueskeys or value types.400 invalid-keyfor disallowed increment keys.403 invalid-gamefor unknown game ids.404 not-foundfor missing entries or invalid increment targets.409 already-votedwhen the same IP votes on the same key twice in a day.
Final Notes
- Secrets: Store the
secretin a secure location (likelocalStorage) if you plan to update or delete this entry later. This API will never return thesecretagain. - Prototype: The
qparameter will change in upcoming versions. Use with caution. - Freeform keys: The segment after
/userdata/is entirely up to you. For example,tests,levels, orplayers. - Admin token: All update (PATCH, PUT) and delete (DELETE) requests can also be made with a
Authorization: AdminToken <your-admin-token>header instead of thesecretin the request body. - Caching: GET responses can be cached briefly. Updates, deletes, increments, and votes invalidate the cache, so repeated GETs may not always refresh access logs.
Defold
There is a Defold Lua Module for AUDS available at: github.com/indiesoftby/defold-poki-auds