API Reference
Overview
The ASD API provides programmatic access to two categories of credentials:
- Tunnel credentials authenticate connections to the tunnel server (tokens or SSH keys)
- API credentials authenticate requests to the ASD API itself (API keys)
All endpoints are hosted at https://asd.engineer/functions/v1/<endpoint>.
API Authentication
API requests use one of three authentication methods:
| Method | Header | When to Use |
|---|---|---|
| None | — | Free token creation (public endpoint) |
| API Key | X-API-Key: sk_<key> | All authenticated operations (scripts, CI/CD, automation) |
| Bearer JWT | Authorization: Bearer <jwt> | Dashboard and CLI sessions, creating your first API key |
API keys are the recommended method for all programmatic access. Create them from the dashboard or via the api-keys-create endpoint.
Bearer JWTs are session tokens issued when you sign in via the dashboard or asd login. You need a JWT to create your first API key (since you do not have an API key yet). After that, use API keys for everything.
Getting Your First API Key
- Sign in at asd.host
- Go to Workspace > API Keys > Create Key
- Select the scopes you need (see Available Scopes)
- Copy the key — it starts with
sk_and is shown only once
Once you have an API key, you can use every authenticated endpoint in this reference.
Tunnel Tokens
Tunnel tokens authenticate connections to the tunnel server. They are a single credential type with three creation methods:
| Token flavor | How you get it | Lifetime | Account required |
|---|---|---|---|
| Free | POST create-ephemeral-token (no auth) | 5 minutes | No |
| Standard | Dashboard or asd login | Until revoked | Yes |
| CI/CD | POST credential-provision (API key auth) | Configurable TTL | Yes |
All token flavors are used the same way once created (see Using tokens below).
Standard tokens, CI/CD tokens, and SSH keys require the Developer plan or above. The Free plan supports free tokens only.
Free tokens (no account)
Get instant tunnel credentials without an account.
POST /functions/v1/create-ephemeral-token
Auth: None
curl -X POST https://asd.engineer/functions/v1/create-ephemeral-token Response (200):
{
"tunnel_client_id": "guest-xyz123",
"tunnel_client_secret": "abc123def456...",
"expires_at": "2026-02-13T12:05:00Z",
"tunnel_host": "eu1.tn.asd.engineer",
"tunnel_port": 2223,
"limits": {
"max_uptime_minutes": 5,
"max_connections_per_hour": 10
}
} Rate limit: 10 requests per hour per IP.
Standard tokens
Create persistent tokens from the web dashboard or CLI.
Dashboard:
- Sign in at asd.host
- Navigate to Workspace > Tunnel Management > Tokens > Create Token
- Copy the
tunnel_userand token value
CLI:
asd login
asd token create asd token create creates ephemeral tunnel credentials and saves them to your .env or global credentials file. Use asd token list to see all stored tokens and asd token use <name> to switch between them.
Standard tokens do not expire unless you revoke them. They are tied to your account and respect your subscription plan limits.
GET /functions/v1/user-tokens-list
List all tunnel tokens for the authenticated user.
Auth: API key or Bearer JWT
curl https://asd.engineer/functions/v1/user-tokens-list
-H "X-API-Key: sk_a1b2c3d4e5f6..." Response (200):
{
"tokens": [
{
"id": "uuid",
"tunnel_user": "user-abc123",
"status": "active",
"tunnel_type": "default",
"created_at": "2026-02-01T10:00:00Z",
"last_used_at": "2026-02-13T08:30:00Z",
"usage_count": 42,
"config_name": "default"
}
]
} POST /functions/v1/revoke-token
Revoke a tunnel token by its tunnel_user identifier.
Auth: API key or Bearer JWT
curl -X POST https://asd.engineer/functions/v1/revoke-token
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{"tunnel_user": "user-abc123"}' CI/CD tokens
Create short-lived tunnel credentials for CI/CD pipelines. Requires an API key with the cicd:provision scope.
POST /functions/v1/credential-provision
Auth: API key with cicd:provision scope
curl -X POST https://asd.engineer/functions/v1/credential-provision
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{
"project": "my-app",
"environment": "staging",
"ttl_minutes": 30
}' Response (200):
{
"token": "tok_...",
"tunnel_user": "user-abc123",
"client_id": "abc123",
"expires_at": "2026-02-13T13:00:00Z",
"ttl_minutes": 30,
"tunnel_host": "eu1.tn.asd.engineer",
"tunnel_port": 2223,
"project_slug": "my-app"
} Rate limit: 60 requests per hour per API key.
Using tokens
All token flavors use the same environment variables:
export ASD_TUNNEL_TOKEN=your-token
export ASD_TUNNEL_USER=your-tunnel-user
asd expose 3000 Or add them to your .env file:
ASD_TUNNEL_TOKEN=your-token
ASD_TUNNEL_USER=your-tunnel-user SSH Key Authentication
Upload SSH public keys for passwordless tunnel access via direct SSH commands.
POST /functions/v1/keys-upload
Upload an SSH public key.
Auth: API key or Bearer JWT
curl -X POST https://asd.engineer/functions/v1/keys-upload
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{
"public_key_ssh": "ssh-ed25519 AAAAC3Nza... user@machine",
"name": "work laptop"
}' Optional fields: server_type, expires_in_days, client_id
Response (200):
{
"key_id": "uuid",
"public_key_fingerprint": "SHA256:abc123...",
"server_type": "shared",
"name": "work laptop",
"expires_at": null
} GET /functions/v1/user-keys-list
List all uploaded SSH keys.
Auth: API key or Bearer JWT
curl https://asd.engineer/functions/v1/user-keys-list
-H "X-API-Key: sk_a1b2c3d4e5f6..." Response (200):
{
"keys": [
{
"id": "uuid",
"name": "work laptop",
"fingerprint": "SHA256:abc123...",
"server_type": "shared",
"status": "active",
"created_at": "2026-02-01T10:00:00Z",
"expires_at": null
}
]
} POST /functions/v1/revoke-ssh-key
Revoke an SSH key by ID. The key must belong to the authenticated user.
Auth: API key or Bearer JWT
curl -X POST https://asd.engineer/functions/v1/revoke-ssh-key
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{ "key_id": "uuid-of-key-to-revoke" }' Response (200):
{ "success": true, "message": "Key revoked successfully" } Errors: 401 (not authenticated), 403 (not the key owner), 404 (key not found or already deleted).
Using SSH Keys
Once uploaded, connect directly via SSH without the ASD CLI:
ssh -p 2223 -R "myapp:80:localhost:3000" your-client-id@eu1.tn.asd.engineer This is useful for CI/CD environments where you cannot install the ASD CLI, or for exposing non-HTTP services (databases, Redis, custom TCP protocols).
API Keys
API keys provide long-lived programmatic access. They use the format sk_<64-char-hex> and support scoped permissions. API keys are the primary way to authenticate automation workflows, including the asd-devinci GitHub Action.
Manage your API keys from the dashboard.
Available Scopes
| Scope | Description |
|---|---|
token:read | Read token information |
token:write | Create and manage tunnel tokens |
config:read | Read tunnel configurations |
config:write | Create and manage tunnel configurations |
apikey:read | Read API key metadata |
apikey:write | Create and manage API keys |
cicd:provision | Provision CI/CD tunnel credentials |
server:admin | Tunnel server administration |
POST /functions/v1/api-keys-create
Create a new API key. The plaintext key is returned only once at creation.
Auth: API key with apikey:write scope, or Bearer JWT
With an existing API key:
curl -X POST https://asd.engineer/functions/v1/api-keys-create
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{
"name": "CI deploy key",
"scopes": ["cicd:provision", "token:write"]
}' With a Bearer JWT (for creating your first API key):
curl -X POST https://asd.engineer/functions/v1/api-keys-create
-H "Authorization: Bearer eyJhbGci..."
-H "Content-Type: application/json"
-d '{
"name": "My first key",
"scopes": ["token:write", "apikey:write"]
}' Optional fields: expires_at (ISO 8601), org_id, team_id
Response (201):
{
"id": "uuid",
"api_key": "sk_a1b2c3d4e5f6...",
"expires_at": "2027-01-01T00:00:00Z",
"message": "API key created. Store it securely -- it cannot be retrieved again."
} GET /functions/v1/user-api-keys-list
List all API keys for the authenticated user. Values are never returned, only metadata.
Auth: API key with apikey:read scope, or Bearer JWT
curl https://asd.engineer/functions/v1/user-api-keys-list
-H "X-API-Key: sk_a1b2c3d4e5f6..." Response (200):
{
"api_keys": [
{
"id": "uuid",
"name": "CI deploy key",
"scopes": ["cicd:provision", "token:write"],
"status": "active",
"created_at": "2026-02-01T10:00:00Z",
"last_used_at": "2026-02-13T08:30:00Z",
"expires_at": "2027-01-01T00:00:00Z"
}
]
} Using API Keys
Pass your API key in the X-API-Key header:
curl -X POST https://asd.engineer/functions/v1/credential-provision
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{"project": "my-app"}' API keys are hashed with bcrypt at creation. ASD stores only the hash and a short prefix for fast lookups. The plaintext key cannot be recovered after creation.
Projects
Register and manage projects for organized credential management.
POST /functions/v1/project-register
Register a new project and optionally create a bound tunnel token.
Auth: API key or Bearer JWT
curl -X POST https://asd.engineer/functions/v1/project-register
-H "X-API-Key: sk_a1b2c3d4e5f6..."
-H "Content-Type: application/json"
-d '{
"slug": "my-app",
"name": "My Application",
"create_token": true
}' Response (200):
{
"project": {
"id": "uuid",
"slug": "my-app",
"name": "My Application",
"default_client_id": "abc123"
},
"token": {
"token": "tok_...",
"tunnel_user": "user-abc123",
"expires_at": null
}
} GET /functions/v1/project-list
List all projects with their bound credentials.
Auth: API key or Bearer JWT
curl https://asd.engineer/functions/v1/project-list
-H "X-API-Key: sk_a1b2c3d4e5f6..." CI/CD Integration
GitHub Actions with asd-devinci
The asd-devinci GitHub Action sets up a full development environment inside CI/CD runners with tunnel access. It uses an API key to provision CI/CD tokens automatically.
name: E2E Tests with Tunnel
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start dev server
run: npm run dev &
- name: Setup tunnel
uses: asd-engineering/asd-devinci@v1
with:
api-key: ${{ secrets.ASD_API_KEY }}
tunnel-name: e2e-${{ github.run_id }}
- name: Run E2E tests
run: npm run test:e2e Setup:
- Create an API key with
cicd:provisionscope from your dashboard - Add
ASD_API_KEYas a repository secret - Use the action in your workflow
Manual CI/CD setup
For CI providers without GitHub Actions support, provision credentials directly:
# Generic CI example
steps:
- run: curl -fsSL https://asd.host/install.sh | bash
- run: |
RESPONSE=$(curl -sf https://asd.engineer/functions/v1/credential-provision
-H "X-API-Key: $ASD_API_KEY"
-H "Content-Type: application/json"
-d '{"project": "my-app", "ttl_minutes": 30}')
export ASD_TUNNEL_TOKEN=$(echo "$RESPONSE" | jq -r '.token')
export ASD_TUNNEL_USER=$(echo "$RESPONSE" | jq -r '.tunnel_user')
asd expose 3000 --name ci-test This pattern works with any CI provider that supports environment variables and shell commands.
Reference
Endpoint Summary
All endpoints are at https://asd.engineer/functions/v1/<endpoint>.
| Endpoint | Method | Auth | Description |
|---|---|---|---|
create-ephemeral-token | POST | None | Create 5-minute tunnel credentials |
credential-provision | POST | API key | Provision CI/CD tunnel credentials |
user-tokens-list | GET | API key or JWT | List your tunnel tokens |
revoke-token | POST | API key or JWT | Revoke a tunnel token |
api-keys-create | POST | API key or JWT | Create a new API key |
user-api-keys-list | GET | API key or JWT | List your API keys |
keys-upload | POST | API key or JWT | Upload an SSH public key |
user-keys-list | GET | API key or JWT | List your SSH keys |
revoke-ssh-key | POST | API key or JWT | Revoke an SSH key |
project-register | POST | API key or JWT | Register a new project |
project-list | GET | API key or JWT | List your projects |
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
ASD_TUNNEL_TOKEN | Yes | — | Tunnel authentication token |
ASD_TUNNEL_USER | Yes | — | Tunnel username / client ID |
ASD_TUNNEL_HOST | No | Auto-detected | Tunnel server hostname |
ASD_TUNNEL_PORT | No | 2223 | Tunnel server SSH port |
ASD_TUNNEL_HOST and ASD_TUNNEL_PORT are returned by the API when creating free or CI/CD tokens. Override them only for self-hosted tunnel servers.
Rate Limits
| Endpoint | Limit | Window |
|---|---|---|
create-ephemeral-token | 10 requests | Per hour, per IP |
credential-provision | 60 requests | Per hour, per API key |
api-keys-create | 20 requests | Per hour, per user |
keys-upload | 20 requests | Per hour, per user |
When you exceed a rate limit, the API returns HTTP 429 with a retry_after value in seconds.
Error Responses
All errors follow a consistent format:
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT",
"retry_after": 3600
} | HTTP Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid request body or missing required fields |
| 401 | UNAUTHORIZED | Missing or invalid authentication |
| 403 | FORBIDDEN | Valid credentials but insufficient permissions |
| 404 | NOT_FOUND | Resource does not exist |
| 429 | RATE_LIMIT | Too many requests. Wait for retry_after. |
| 500 | INTERNAL_ERROR | Server error. Retry after a few seconds. |
Related Guides
- Security and Authentication — HTTP Basic Auth, tunnel tokens, per-service access control
- Understanding Tunnels — how tunnels work, HTTP vs TCP, WebSocket support
- Vault — encrypted secret management for API keys and credentials
- CLI Command Reference — all ASD CLI commands