REST API Reference

The Celiq API lets you query your data warehouse, retrieve semantic layer definitions, and embed Celiq data into your own applications. Available on the Team plan.

ℹ️ The API is available on the Team plan ($199/mo). Upgrade →

Base URL

Base URL https://app.celiq.co/api/v1

All API requests must use HTTPS. HTTP requests will be rejected.

Authentication

Authenticate using an API key in the Authorization header. Create API keys in your workspace under Lumen → API Keys.

curl https://app.celiq.co/api/v1/workspace \
  -H "Authorization: Bearer clq_your_api_key_here"
⚠️ API keys are shown only once at creation time. Store them securely. Never commit API keys to source code or expose them in client-side code.

Key format

All Celiq API keys begin with clq_ followed by 64 hex characters. Keys can be revoked at any time from the API Keys page.

Rate limits

PlanRequests/minuteQueries/day
Team60Unlimited

Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Workspace

GET /workspace Get workspace details

Response

{
  "workspace": {
    "id": "d3e30ecc-...",
    "name": "Tickete",
    "plan": "team",
    "created_at": "2026-01-15T10:30:00Z"
  }
}

Projects

GET /projects List all projects

Response

{
  "projects": [
    {
      "id": "71d4bbc2-...",
      "name": "Production Analytics",
      "slug": "production-analytics",
      "created_at": "2026-01-15T10:30:00Z"
    }
  ]
}

Nodes

GET /projects/:slug/nodes List all nodes in a project

Path parameters

ParameterTypeDescription
slug required string Project slug (e.g. production-analytics)

Response

{
  "nodes": [
    {
      "id": "...",
      "name": "orders",
      "status": "active",
      "content": "node: orders\nlabel: \"Orders\"\n...",
      "cml": "node: orders\nlabel: \"Orders\"\n...",
      "created_at": "2026-01-15T10:30:00Z"
    }
  ]
}
GET /projects/:slug/nodes/:name Get a single node with full CML content

Path parameters

ParameterTypeDescription
slug required string Project slug
name required string Node name (e.g. orders)

Response

{
  "node": {
    "id": "...",
    "name": "orders",
    "content": "node: orders\nlabel: \"Orders\"\n...",
    "cml": "node: orders\nlabel: \"Orders\"\n...",
    "created_at": "2026-01-15T10:30:00Z"
  }
}

Query

Run a raw SQL query against a connection in your workspace. Only SELECT, WITH, and EXPLAIN statements are allowed. Results are capped at 1,000 rows.

POST /query Run a SQL query, get JSON results

Request body

ParameterTypeDescription
connection_id required string UUID of the connection to query against
sql required string SQL query (SELECT, WITH, or EXPLAIN only)
limit optional integer Max rows to return. Default: 1000. Max: 1000.

Example request

curl -X POST https://app.celiq.co/api/v1/query \
  -H "Authorization: Bearer clq_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "71d4bbc2-...",
    "sql": "SELECT country, SUM(revenue) AS total_revenue FROM orders GROUP BY 1 ORDER BY 2 DESC LIMIT 10"
  }'

Response

{
  "columns": ["country", "total_revenue"],
  "rows": [
    { "country": "India", "total_revenue": 124500 },
    { "country": "US",    "total_revenue": 87200 }
  ],
  "row_count": 2
}

Errors

The API uses standard HTTP status codes. Error responses include an error field with a human-readable message.

StatusMeaning
200Success
400Bad request — missing or invalid parameters
401Unauthorized — missing or invalid API key
403Forbidden — API access requires Team plan
404Not found — project or node doesn't exist
429Rate limit exceeded
500Internal server error

Error response format

{
  "error": "Project not found"
}

SDKs & examples

Official SDKs are coming soon. In the meantime, the API works with any HTTP client.

Example: Daily Slack report

// Send yesterday's revenue to Slack every morning
const res = await fetch('https://app.celiq.co/api/v1/query', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${process.env.CELIQ_API_KEY}` },
  body: JSON.stringify({
    connection_id: process.env.CELIQ_CONNECTION_ID,
    sql: "SELECT SUM(revenue) AS total_revenue, COUNT(*) AS order_count FROM orders WHERE order_date = CURRENT_DATE - 1",
  }),
});
const { rows } = await res.json();
// Post to Slack
await slack.chat.postMessage({
  channel: '#metrics',
  text: `Yesterday: ₹${rows[0].total_revenue.toLocaleString()} revenue, ${rows[0].order_count} orders`,
});

Example: Export to CSV (Python)

import requests, csv

r = requests.post('https://app.celiq.co/api/v1/query',
  headers={'Authorization': 'Bearer clq_your_key'},
  json={
    'connection_id': '71d4bbc2-...',
    'sql': 'SELECT * FROM orders LIMIT 1000',
  }
)
data = r.json()['rows']

with open('orders.csv', 'w') as f:
    writer = csv.DictWriter(f, fieldnames=data[0].keys())
    writer.writeheader()
    writer.writerows(data)