Getting started

From zero to your first API call in minutes.

Authenticate, make a request, and handle errors. This guide covers everything you need to start building on the wrk!ng platform.

Base URL

EnvironmentURL
Productionhttps://api.wrk.ing
Local developmenthttp://localhost:3001

All endpoints are prefixed with /api. For example, the health check lives at https://api.wrk.ing/api/health.

Authentication

The API supports two authentication methods. Both use the Authorization: Bearer <token> header.

Authentication flow diagram showing two paths: JWT tokens for interactive browser sessions, and API keys for server-to-server integrations — both converging on the Authorization: Bearer header.

Authenticate with email, password, and organization slug to receive short-lived tokens. This method is designed for browser-based applications and tools that operate on behalf of a logged-in user.

curl -X POST https://api.wrk.ing/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com",
    "password": "your-password",
    "org_slug": "acme"
  }'

A successful response returns an access token and a refresh token:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
  "expires_in": 900,
  "user": {
    "id": 42,
    "org_id": 1,
    "org_name": "Acme Corp",
    "email": "you@example.com"
  }
}

Use the access_token as your Bearer token for subsequent requests.

For automated systems, CI pipelines, and integrations that don't involve a user session, create an API key. Keys are scoped to your organization and never expire unless you set an expiration or revoke them.

Create a key through the admin UI or the API:

curl -X POST https://api.wrk.ing/api/api-keys \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{  "name": "CI pipeline" }'

Store your key immediately

The response includes the raw key. It is only shown once -- you cannot retrieve it later. Store it in a secrets manager or environment variable right away.

{
  "id": 7,
  "name": "CI pipeline",
  "prefix": "wrk_a1b2c3d4",
  "key": "wrk_a1b2c3d4e5f6...64 hex characters total"
}

API keys follow the format wrk_ followed by 64 hexadecimal characters. Use the full key as a Bearer token:

curl https://api.wrk.ing/api/users/me \
  -H "Authorization: Bearer wrk_a1b2c3d4e5f6..."

Your first request

Start with the unauthenticated health check to confirm connectivity:

curl https://api.wrk.ing/api/health
const res = await fetch("https://api.wrk.ing/api/health");
const data = await res.json();
console.log(data); // { status: "ok" }
import requests

r = requests.get("https://api.wrk.ing/api/health")
print(r.json())  # {"status": "ok"}
{ "status": "ok" }

Then make an authenticated request to verify your token:

curl https://api.wrk.ing/api/users/me \
  -H "Authorization: Bearer $TOKEN"
const me = await fetch("https://api.wrk.ing/api/users/me", {
  headers: { Authorization: `Bearer ${token}` },
});
const user = await me.json();
console.log(user);
headers = {"Authorization": f"Bearer {token}"}
me = requests.get("https://api.wrk.ing/api/users/me", headers=headers)
print(me.json())

Token refresh

Access tokens are short-lived. When one expires, exchange the refresh token for a new pair instead of re-authenticating with credentials:

curl -X POST https://api.wrk.ing/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{  "refresh_token": "dGhpcyBpcyBhIHJlZnJl..." }'
async function refreshTokens(refreshToken) {
  const res = await fetch("https://api.wrk.ing/api/auth/refresh", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ refresh_token: refreshToken }),
  });
  if (!res.ok) throw new Error("Refresh failed");
  return res.json();
}
def refresh_tokens(refresh_token):
    r = requests.post(
        "https://api.wrk.ing/api/auth/refresh",
        json={"refresh_token": refresh_token},
    )
    r.raise_for_status()
    return r.json()

One-time use

The response has the same shape as the login response, with fresh access_token and refresh_token values. The old refresh token is invalidated on use.

Error format

All errors return a JSON body with an error field. Validation failures include a details object with per-field information.

General error:

{
  "error": "Invalid credentials"
}

Validation error (422):

{
  "error": "Validation failed",
  "details": {
    "fieldErrors": {
      "email": ["Invalid email"]
    },
    "formErrors": []
  }
}

Common status codes

CodeMeaning
200Success
201Created
204Deleted (no content)
401Authentication required or token expired
403Insufficient permissions
404Resource not found
422Validation failed
429Rate limit exceeded
500Internal server error

Rate limiting

The API enforces rate limits to ensure fair usage. When you exceed the limit, the API returns a 429 status code. Back off and retry after the duration indicated in the Retry-After header.

OpenAPI specification

A machine-readable OpenAPI 3.0 spec is available at:

https://api.wrk.ing/api/docs.json

You can load this into any OpenAPI-compatible tool (Postman, Insomnia, Swagger UI) to explore all available endpoints, request/response schemas, and authentication requirements. The interactive API reference is also available at /developers/api.

Tools and downloads

Ready-made resources

Get up and running faster with pre-built collections you can import into your favourite tools.