Core API — Usage Reports & Credit Balance
The Core API returns your account's API usage and credit balance as JSON, the same figures as your dashboard, so you can build your own reports, dashboards and alerts. It takes the API key you already use; every endpoint is GET, calls are free and do not appear in your usage, and responses carry no personal data.
- Base URL:
https://iapp.co.th/api/core/v1 - Header:
apikey: YOUR_API_KEY(x-api-keyalso works). Your key is in API Key Management.
curl "https://iapp.co.th/api/core/v1/credits" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"balance": 1234.56,
"currency": "IC",
"validUntil": "2027-01-31T16:59:59.000Z"
}
}
Call it from a server, a scheduled job or a BI tool, never from browser JavaScript: the key would be readable in the page source, and browser calls are blocked by CORS.
Endpoints
| Endpoint | Returns |
|---|---|
/ping | Confirms the key works |
/credits | Remaining credit balance in IC |
/usage/summary | Headline figures for a period: requests, credits, average latency, success rate, top endpoints |
/usage/timeseries | Requests and credits per hour, day, week or month |
/usage/services | One row per service: requests, credits, latency, error rate |
/usage/keys | One row per API key, with its name |
/usage/records | One row per call, with filters, sorting and pagination |
Every /usage/* endpoint takes startDate and endDate (YYYY-MM-DD or ISO 8601; default the last 30 days). All but /usage/keys also take apiKeyId to report on one key.
Parameters and responses
- /usage/summary
- /usage/timeseries
- /usage/services
- /usage/keys
- /usage/records
- /ping
No parameters beyond the shared ones.
curl "https://iapp.co.th/api/core/v1/usage/summary?startDate=2026-08-01&endDate=2026-08-05" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"period": { "startDate": "2026-08-01T00:00:00.000Z", "endDate": "2026-08-05T00:00:00.000Z" },
"totalRequests": 18342,
"totalCredits": 2311.75,
"avgLatencyMs": 412,
"successRate": 99.12,
"topEndpoints": [
{ "endpoint": "/thai-ocr/v3.5/ocr-document", "requests": 9120, "credits": 1824.0 },
{ "endpoint": "/v3/store/data/thai-legal/search", "requests": 4210, "credits": 421.0 }
]
}
}
groupBy: hour, day (default), week or month. Bucket timestamps are UTC; convert them to local time when rendering.
curl "https://iapp.co.th/api/core/v1/usage/timeseries?startDate=2026-08-01&endDate=2026-08-05&groupBy=day" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"period": { "startDate": "2026-08-01T00:00:00.000Z", "endDate": "2026-08-05T00:00:00.000Z" },
"groupBy": "day",
"points": [
{ "date": "2026-08-01T00:00:00.000Z", "requests": 4102, "credits": 512.25 },
{ "date": "2026-08-02T00:00:00.000Z", "requests": 3876, "credits": 488.5 },
{ "date": "2026-08-03T00:00:00.000Z", "requests": 5211, "credits": 651.0 }
]
}
}
sortBy: requests (default), credits, latency or errorRate. sortOrder: desc (default) or asc.
curl "https://iapp.co.th/api/core/v1/usage/services?sortBy=credits&sortOrder=desc" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"period": { "startDate": "2026-07-06T09:30:00.000Z", "endDate": "2026-08-05T09:30:00.000Z" },
"services": [
{ "service": "document-ocr", "requests": 9120, "credits": 1824.0, "avgLatencyMs": 890, "errorRate": 0.4 },
{ "service": "thai-legal", "requests": 4210, "credits": 421.0, "avgLatencyMs": 210, "errorRate": 0.1 }
]
}
}
sortBy: requests (default), credits or lastUsed. sortOrder: desc (default) or asc.
curl "https://iapp.co.th/api/core/v1/usage/keys?startDate=2026-08-01" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"period": { "startDate": "2026-08-01T00:00:00.000Z", "endDate": "2026-08-24T00:00:00.000Z" },
"keys": [
{
"keyId": "0d9c7c2e-59a4-4f6b-9f1e-3f6f6f0a1b2c",
"keyName": "customer-a-production",
"keyPrefix": "iapp_live_ab",
"requests": 9120,
"credits": 1824.0,
"errorRate": 0.4,
"avgLatencyMs": 890,
"lastUsedAt": "2026-08-23T14:22:31.000Z"
},
{
"keyId": "b4f0a2d1-7c3e-4d5a-8e9f-1a2b3c4d5e6f",
"keyName": "customer-b-production",
"keyPrefix": "iapp_live_cd",
"requests": 4210,
"credits": 421.0,
"errorRate": 0.1,
"avgLatencyMs": 210,
"lastUsedAt": "2026-08-24T08:01:12.000Z"
}
]
}
}
| Parameter | Values |
|---|---|
service | A service value from /usage/services |
method | GET, POST, PUT, DELETE, PATCH |
status | One HTTP status, e.g. 402 |
statusClass | 2xx, 3xx, 4xx, 5xx; ignored when status is set |
minCredits | Only calls that cost at least this many IC |
sortBy | timestamp (default), credits, latency, status |
sortOrder | desc (default), asc |
limit | Rows per page, 1–1000, default 100 |
offset | Default 0; limit + offset ≤ 10,000, so narrow the dates to go further |
To page, raise offset by limit until hasMore is false.
# The 50 most expensive calls since 1 August
curl "https://iapp.co.th/api/core/v1/usage/records?startDate=2026-08-01&sortBy=credits&sortOrder=desc&limit=50" \
-H "apikey: YOUR_API_KEY"
# Failed calls (4xx) to one service, oldest first
curl "https://iapp.co.th/api/core/v1/usage/records?service=document-ocr&statusClass=4xx&sortBy=timestamp&sortOrder=asc" \
-H "apikey: YOUR_API_KEY"
# One key's calls
curl "https://iapp.co.th/api/core/v1/usage/records?apiKeyId=0d9c7c2e-59a4-4f6b-9f1e-3f6f6f0a1b2c&startDate=2026-08-01" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"period": { "startDate": "2026-08-01T00:00:00.000Z", "endDate": "2026-08-05T09:30:00.000Z" },
"records": [
{
"timestamp": "2026-08-04T14:22:31.000Z",
"service": "document-ocr",
"endpoint": "/thai-ocr/v3.5/ocr-document",
"method": "POST",
"status": 402,
"credits": 0,
"latencyMs": 18,
"apiKeyPrefix": "iapp_liv...",
"keyId": "0d9c7c2e-59a4-4f6b-9f1e-3f6f6f0a1b2c",
"keyName": "customer-a-production"
}
],
"pagination": { "total": 3, "limit": 100, "offset": 0, "hasMore": false }
}
}
curl "https://iapp.co.th/api/core/v1/ping" \
-H "apikey: YOUR_API_KEY"
{
"success": true,
"data": {
"ok": true,
"apiKeyPrefix": "iapp_liv...",
"timestamp": "2026-08-05T09:30:00.000Z"
}
}
Per-key reporting
Create one API key per application or customer in API Key Management. /usage/keys returns one row per key with its keyId, the key's id and never the key itself; pass it as apiKeyId to any other /usage/* endpoint to scope that report to the key. A deleted key still appears, with keyId, keyName and keyPrefix set to null, so account totals reconcile.
Examples
- Python: daily cost report
- Node.js: low-balance alert
import requests
BASE = "https://iapp.co.th/api/core/v1"
HEADERS = {"apikey": "YOUR_API_KEY"}
credits = requests.get(f"{BASE}/credits", headers=HEADERS).json()["data"]
series = requests.get(
f"{BASE}/usage/timeseries",
headers=HEADERS,
params={"startDate": "2026-08-01", "groupBy": "day"},
).json()["data"]
print(f"Balance: {credits['balance']:.2f} IC")
for point in series["points"]:
print(f"{point['date'][:10]} {point['requests']:>6} calls {point['credits']:>8.2f} IC")
Run it from cron.
const BASE = "https://iapp.co.th/api/core/v1";
const THRESHOLD = 100; // IC
const res = await fetch(`${BASE}/credits`, {
headers: { apikey: process.env.IAPP_API_KEY },
});
const { data } = await res.json();
if (data.balance < THRESHOLD) {
await notifySlack(`iApp credits low: ${data.balance} IC left`);
}
For Postman, import the collection and the production environment, then set the apikey variable.
Limits
- 120 requests a minute per API key; beyond that, HTTP 429. For a dashboard, a poll every 30 to 60 seconds is enough.
- A call appears in the usage records within seconds; the credit balance is real time.
- History is kept as long as the web dashboard keeps it. To archive it, pull
/usage/recordson a schedule and store the rows.
Data handling
The API is read-only: it cannot create keys, spend credits, change settings or delete anything. Responses carry no name, email, user ID, client IP, request headers or request and response contents; endpoint paths lose their query strings, and API keys appear only as prefixes, never in full. A key reaches only its own account, and an apiKeyId that is not one of its keys returns 404; if a key leaks, revoke it in API Key Management and its usage history stays.
Errors
| HTTP | Code | Meaning |
|---|---|---|
400 | VALIDATION_ERROR | A bad parameter; error.details.errors lists each problem |
401 | UNAUTHORIZED | Missing or invalid API key |
403 | FORBIDDEN | Account not active |
404 | NOT_FOUND | apiKeyId is not one of this account's keys |
429 | TOO_MANY_REQUESTS | Over 120 requests a minute for this key |
503 | SERVICE_UNAVAILABLE | Temporary backend issue; retry with backoff |
Every error has one shape:
{
"success": false,
"error": { "code": "UNAUTHORIZED", "message": "Invalid API key." }
}