Skip to main content

Custom APIs

Rill lets you create custom API endpoints that return data from your project as JSON over HTTP. Define a YAML file, write a SQL query, and you have an API — no backend code required.

Custom APIs are ideal for:

  • Powering internal tools — feed Rill data into dashboards, Slack bots, or scripts
  • Building customer-facing integrations — expose filtered data to external applications
  • Automating workflows — pull data into CI/CD pipelines, scheduled jobs, or ETL processes
  • Multi-tenant data access — serve different data to different customers using custom attributes

API types

Rill supports two types of custom APIs:

TypeBest forQuery target
SQL APIQuerying models, tables, or external databases directlyAny model, table, or external connector (DuckDB, BigQuery, Snowflake, etc.)
Metrics SQL APIQuerying metrics views using dimension and measure namesMetrics views (inherits security policies automatically)

Your first custom API

1. Create an API file

Create a YAML file in your project's apis/ directory. For example, apis/top-publishers.yaml:

type: api
sql: |
SELECT publisher, COUNT(*) as total_records
FROM ad_bids
GROUP BY publisher
ORDER BY total_records DESC
LIMIT 10

2. Test it locally

With Rill Developer running (rill start), call your API at:

curl "http://localhost:9009/v1/instances/default/api/top-publishers"

You'll get a JSON response:

[
{"publisher": "Facebook", "total_records": 15234},
{"publisher": "Google", "total_records": 12876},
{"publisher": "Microsoft", "total_records": 9541}
]
note

Local development does not require authentication. When deployed to Rill Cloud, all API calls require a bearer token.

3. Deploy and call from Rill Cloud

After deploying your project, call the API with authentication:

curl "https://api.rilldata.com/v1/organizations/<org>/projects/<project>/runtime/api/top-publishers" \
-H "Authorization: Bearer <token>"

See Calling APIs for full details on authentication and calling APIs.

Make it dynamic

Add templating to make your API accept parameters:

type: api
sql: |
SELECT publisher, COUNT(*) as total_records
FROM ad_bids
WHERE domain = '{{ .args.domain }}'
GROUP BY publisher
ORDER BY total_records DESC
LIMIT {{ default 10 .args.limit }}

Call it with query parameters:

curl "http://localhost:9009/v1/instances/default/api/top-publishers?domain=google.com&limit=5"

Add access control

Use security rules to control who can access your API and what data they see:

type: api
sql: |
SELECT publisher, domain, COUNT(*) as total_records
FROM ad_bids
WHERE customer_id = '{{ .user.customer_id }}'
GROUP BY publisher, domain
security:
access: true

Each customer sees only their own data, based on the custom attributes in their token.

Next steps