API Reference
The Overscore API powers query execution and dashboard deployment. All endpoints are served from overscore.dev.
Authentication
Requests are authenticated using one of two methods:
- API key — passed in the request body as
apiKey. Used by deployed dashboards to execute queries. - Session cookie — set automatically when you sign in to the Hub via Google OAuth. Used by the Hub UI and CLI.
API keys are scoped to a project. A valid API key can execute any registered query within that project.
POST /api/query
Execute a registered query against BigQuery and return the results. This is the endpoint that the useQuery hook calls under the hood.
Request
POST https://overscore.dev/api/query
Content-Type: application/json
Body:
{
"projectSlug": "acme",
"dashboardSlug": "sales-dashboard",
"queryName": "revenue_by_month",
"apiKey": "os_live_abc123..."
}
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| projectSlug | string | Yes | Your project's unique slug |
| dashboardSlug | string | Yes | The dashboard this query belongs to |
| queryName | string | Yes | The registered query name to execute |
| apiKey | string | Yes | Your project's API key |
Response
Success (200):
{
"data": [
{ "month": "2025-01", "total_revenue": 52400 },
{ "month": "2025-02", "total_revenue": 61300 },
{ "month": "2025-03", "total_revenue": 58900 }
],
"metadata": {
"rowCount": 3,
"executionTimeMs": 1240,
"cached": false,
"cacheUrl": null
}
}
When caching is enabled and the cache is fresh:
{
"data": [
{ "month": "2025-01", "total_revenue": 52400 },
{ "month": "2025-02", "total_revenue": 61300 }
],
"metadata": {
"rowCount": 2,
"executionTimeMs": 12,
"cached": true,
"cacheUrl": "https://overscore.dev/cache/acme/sales-dashboard/revenue_by_month.parquet",
"cacheTtl": 3600,
"cacheExpiresAt": "2025-06-15T13:00:00Z"
}
}
| Field | Type | Description |
|-------|------|-------------|
| data | array | Array of row objects. Each key is a column name. |
| metadata.rowCount | number | Total number of rows returned |
| metadata.executionTimeMs | number | Time to execute (BigQuery time, or cache retrieval time) |
| metadata.cached | boolean | Whether the result was served from cache |
| metadata.cacheUrl | string or null | URL to the Parquet file, if cached |
| metadata.cacheTtl | number | Cache TTL in seconds (only present when cached) |
| metadata.cacheExpiresAt | string | ISO 8601 expiration timestamp (only present when cached) |
Error responses
401 Unauthorized — invalid or missing API key:
{
"error": "Invalid API key"
}
404 Not Found — query not registered:
{
"error": "Query 'revenue_by_month' is not registered for dashboard 'sales-dashboard'"
}
500 Internal Server Error — BigQuery execution failure:
{
"error": "Query execution failed",
"detail": "BigQuery error: Table not found: my-project.analytics.orders"
}
POST /api/deploy
Deploy a built dashboard to Overscore. This endpoint accepts a multipart upload containing the build artifacts.
Request
POST https://overscore.dev/api/deploy
Content-Type: multipart/form-data
Authorization: Bearer <session-token>
Form fields:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| projectSlug | string | Yes | Your project's unique slug |
| dashboardSlug | string | Yes | The dashboard slug to deploy to |
| bundle | file | Yes | Gzipped tar of the dist/ build output |
The Authorization header uses the session token obtained from overscore login. The CLI handles this automatically.
Response
Success (200):
{
"success": true,
"url": "https://acme.overscore.dev/sales-dashboard/",
"deployment": {
"id": "dep_abc123",
"createdAt": "2025-06-15T12:30:00Z",
"sizeBytes": 245760
}
}
| Field | Type | Description |
|-------|------|-------------|
| success | boolean | Whether the deployment succeeded |
| url | string | The live URL of the deployed dashboard |
| deployment.id | string | Unique deployment identifier |
| deployment.createdAt | string | ISO 8601 timestamp of the deployment |
| deployment.sizeBytes | number | Total size of the uploaded bundle |
Error responses
401 Unauthorized — missing or expired session:
{
"error": "Authentication required. Run 'overscore login' to sign in."
}
403 Forbidden — user is not an admin or owner of the project:
{
"error": "You do not have permission to deploy to this project"
}
413 Payload Too Large — bundle exceeds the size limit:
{
"error": "Bundle size exceeds the 50MB limit"
}
Rate limits
API requests are rate-limited per project:
| Endpoint | Limit |
|----------|-------|
| POST /api/query | 100 requests per minute |
| POST /api/deploy | 10 deployments per hour |
When rate limited, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait.
Next steps
- Authentication — how API keys and session auth work in detail
- Data Caching — Parquet caching and DuckDB-WASM
- CLI Reference — the CLI commands that call these endpoints