Skip to main content

Calling Custom APIs

Custom APIs are exposed as HTTP endpoints that return JSON. You can call them from any language or tool that supports HTTP requests.

API endpoints​

Rill Cloud​

https://api.rilldata.com/v1/organizations/<org-name>/projects/<project-name>/runtime/api/<api-name>

This targets the project's production deployment. To call the API on the deployment for a specific branch (e.g. a dev/preview deployment), insert /branch/<branch-name> before /runtime:

https://api.rilldata.com/v1/orgs/<org-name>/projects/<project-name>/branch/<branch-name>/runtime/api/<api-name>

Local development​

http://localhost:9009/v1/instances/default/api/<api-name>

Where <api-name> is the name of your API file without the .yaml extension (e.g., my-api.yaml → my-api).

Making requests​

Custom APIs accept both GET and POST requests.

GET with query parameters​

curl "https://api.rilldata.com/v1/organizations/<org>/projects/<project>/runtime/api/my-api?domain=google.com&limit=10" \
-H "Authorization: Bearer <token>"

POST with JSON body​

curl -X POST "https://api.rilldata.com/v1/organizations/<org>/projects/<project>/runtime/api/my-api" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"domain": "google.com", "limit": 10}'

Both methods produce the same result. If you provide both query parameters and a JSON body, query parameters take precedence.

Response format​

APIs return a JSON array of objects:

[
{"publisher": "Facebook", "domain": "google.com", "total": 15234},
{"publisher": "Google", "domain": "google.com", "total": 12876}
]

Testing locally​

Local development does not require authentication:

# GET request
curl "http://localhost:9009/v1/instances/default/api/my-api?domain=google.com"

# POST request
curl -X POST http://localhost:9009/v1/instances/default/api/my-api \
-H "Content-Type: application/json" \
-d '{"domain": "google.com"}'
note

User attributes ({{ .user.* }}) are not available during local testing since no authentication token is provided. To test with user attributes, deploy to Rill Cloud and use a service token with custom attributes.

Authentication​

Rill Cloud APIs require a bearer token in the Authorization header.

For development and testing​

Create a user token (inherits your personal permissions):

rill token issue --display-name "API Testing"
# Returns: rill_usr_...

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

For production systems​

Create a service token with optional custom attributes:

rill service create my-api-service \
--project my-project \
--project-role viewer \
--attributes '{"customer_id": "acme-corp"}'
# Returns: rill_svc_...

Custom attributes on the token are available in your API templates as {{ .user.customer_id }}. See Security & Access Control for details on how to use custom attributes to build multi-tenant APIs.

note

If you need short-lived tokens with custom attributes for end users, use the ephemeral token feature instead of creating a service token per user.

Token Documentation

For full guidance on token types, roles, and management:

OpenAPI schema​

Rill automatically generates an OpenAPI spec for your project. Download it to generate typed clients:

# From Rill Cloud
curl "https://api.rilldata.com/v1/organizations/<org>/projects/<project>/runtime/api/openapi" \
-H "Authorization: Bearer <token>" \
-o openapi.json

# Locally
curl http://localhost:9009/v1/instances/default/api/openapi -o openapi.json

See OpenAPI Documentation for how to add request and response schemas to your API definitions.