Core API — Usage Reports & Credit Balance
Build your own dashboard on top of your iApp account. The Core API exposes your API usage and credit data as clean, read-only JSON — the same numbers that power the iApp dashboard — so you can pull them into Grafana, Google Sheets, your admin panel, a Slack bot, or anything else that speaks HTTP.
- Same API key you already use for AI APIs — no extra setup
- Read-only by design — every endpoint is
GET; a leaked key can never modify your account through this API - No PII — responses contain only technical telemetry (timestamps, paths, status codes, credits, latency); never names, emails, IPs, or request contents
- Per-key reporting — issue one API key per application or end customer and meter each key separately
- Free — Core API calls do not consume credits
Base URL: https://iapp.co.th/api/core/v1
Visit API Key Management to view your key or request a new one.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /ping | Verify your API key works |
GET | /credits | Remaining credit balance |
GET | /usage/summary | Aggregate usage statistics for a date range |
GET | /usage/timeseries | Usage over time (hour/day/week/month buckets) — chart-ready |
GET | /usage/services | Per-service breakdown (requests, credits, latency, error rate) |
GET | /usage/keys | Per-API-key breakdown — one row per key, with the key's name |
GET | /usage/records | Individual API calls with filter, sort and pagination |
All endpoints require the apikey header. Unless stated otherwise, date parameters accept YYYY-MM-DD or full ISO 8601 datetimes, and the default reporting window is the last 30 days.
Authentication
Pass your API key in the apikey header (the x-api-key header also works):
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"
}
}
Call the Core API from your backend, scheduled job, or BI tool — never from browser JavaScript. Anyone who can read your page source can read your API key. (Browser calls are additionally blocked by CORS on purpose.)
Credit balance
GET /credits — your remaining iApp Credits (IC).
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"
}
}
Perfect for a low-balance alert: poll once an hour and page yourself when balance drops below your threshold.
Usage summary
GET /usage/summary — the headline numbers for a period.
| Parameter | Type | Default | Description |
|---|---|---|---|
startDate | date | 30 days ago | Period start |
endDate | date | now | Period end |
apiKeyId | uuid | — | Only calls made with this API key — a keyId from /usage/keys |
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 }
]
}
}
Usage timeseries
GET /usage/timeseries — requests and credits per time bucket, ready to feed straight into a chart library.
| Parameter | Type | Default | Description |
|---|---|---|---|
startDate | date | 30 days ago | Period start |
endDate | date | now | Period end |
groupBy | enum | day | hour, day, week, or month |
apiKeyId | uuid | — | Only calls made with this API key — a keyId from /usage/keys |
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 }
]
}
}
Bucket timestamps are UTC — convert to your local timezone when rendering.
Per-service breakdown
GET /usage/services — one row per iApp service you called, with quality metrics.
| Parameter | Type | Default | Description |
|---|---|---|---|
startDate / endDate | date | last 30 days | Reporting period |
sortBy | enum | requests | requests, credits, latency, or errorRate |
sortOrder | enum | desc | asc or desc |
apiKeyId | uuid | — | Only calls made with this API key — a keyId from /usage/keys |
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 }
]
}
}
Usage by key
GET /usage/keys — one row per API key used in the period. This is the endpoint for reseller and multi-tenant setups: create one key per application or end customer in API Key Management, and each row meters one of them.
| Parameter | Type | Default | Description |
|---|---|---|---|
startDate / endDate | date | last 30 days | Reporting period |
sortBy | enum | requests | requests, credits, or lastUsed |
sortOrder | enum | desc | asc or desc |
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"
}
]
}
}
keyId is the key's id from API Key Management — never the key itself. Pass it as the apiKeyId parameter on /usage/summary, /usage/timeseries, /usage/services, or /usage/records to scope any report to that key. A key that has been deleted from the account still appears (so account totals reconcile) with keyId, keyName, and keyPrefix set to null.
Usage records — filter, sort, paginate
GET /usage/records — the raw call log, one row per API request. This is the workhorse endpoint for custom reporting.
| Parameter | Type | Default | Description |
|---|---|---|---|
startDate / endDate | date | last 30 days | Reporting period |
service | string | — | Only calls to this service (use the service values from /usage/services) |
method | enum | — | GET, POST, PUT, DELETE, PATCH |
status | int | — | Exact HTTP status, e.g. 402 |
statusClass | enum | — | 2xx, 3xx, 4xx, or 5xx (ignored when status is set) |
minCredits | number | — | Only calls that cost at least this many IC |
apiKeyId | uuid | — | Only calls made with this API key — a keyId from /usage/keys |
sortBy | enum | timestamp | timestamp, credits, latency, or status |
sortOrder | enum | desc | asc or desc |
limit | int | 100 | Rows per page, 1–1000 |
offset | int | 0 | Pagination offset (limit + offset ≤ 10,000 — narrow the date range to go deeper) |
Example — my 50 most expensive calls this month:
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"
Example — all failed calls (4xx) to a 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"
Example — one key's calls (per-customer reporting):
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 }
}
}
Paging: repeat the request increasing offset by limit until hasMore is false.
Postman collection
Prefer clicking to curling? Import the ready-made collection — all seven endpoints, toggleable filter examples, and 66 built-in assertions (including PII-leak checks):
Import the collection plus an environment, set the apikey environment variable, and go.
Build a dashboard in 20 lines
Python — daily cost report:
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")
Node.js — low-balance alert (run 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`);
}
Safety & privacy design
The Core API is built so that even in the worst case — your API key leaks — the damage is contained:
- Read-only. Only
GETendpoints exist. There is no way to create keys, spend credits, change settings, or delete anything through this API. - No PII. Responses never include your name, email, user ID, client IP addresses, request headers, or the contents of your API requests/responses. Endpoint paths are stripped of query strings (which could contain input data), and API keys appear only as 8-character prefixes.
- Your data only. The key identifies your account; there is no parameter that can reach another account's data. The
apiKeyIdfilter accepts only ids of your own keys — any other value returns404. - Rate-limited. 120 requests/minute per API key. Responses beyond that return HTTP 429 — poll dashboards at a sensible interval (the data is near-real-time; every 30–60 s is plenty).
If your key does leak, revoke it in API Key Management — usage history stays intact.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid API key |
403 | FORBIDDEN | Account not active |
400 | VALIDATION_ERROR | Bad parameter — the response's error.details.errors lists each problem |
404 | NOT_FOUND | apiKeyId is not one of this account's keys |
429 | TOO_MANY_REQUESTS | Rate limit exceeded (120/min per key) |
503 | SERVICE_UNAVAILABLE | Temporary backend issue — retry with backoff |
All errors share one shape:
{
"success": false,
"error": { "code": "UNAUTHORIZED", "message": "Invalid API key." }
}
FAQ
Does calling the Core API cost credits? No — it's free and doesn't appear in your usage records.
How fresh is the data? Usage records appear within seconds of the API call completing; credit balance is real-time.
Can I get data older than my dashboard shows? Records are served from our analytics store with the same retention as the web dashboard. For long-term archival, pull /usage/records periodically and store the rows on your side.
Can I use a separate key just for reporting? Yes — create a dedicated key in API Key Management and use it only for the Core API. Each record row shows which key (keyId, keyName) made the original call.
Can I report usage per customer or per application? Yes — create one API key per customer or application, then use /usage/keys for the per-key breakdown and the apiKeyId parameter to scope any other usage endpoint to a single key.