API Keys

Create API Key

Programmatically create a new API key for your account.

POST /api/user/api-keys

Creates a new API key scoped to your user account (and its organizations). To create a key owned by an organization instead, see Create Organization API Key.

This endpoint accepts only your logged-in dashboard session. API keys can't create keys: any API key gets 401. Send your session cookie with the request. On Rybbit Cloud the session must have an active organization (the one you last opened in the dashboard), or the request returns 400 with "No active organization"; its plan decides whether you can create keys.

Request Body

Prop

Type

Scopes use the resource:action taxonomy listed under Roles and Scopes. Per-key limits don't apply; usage counts against the owner's rate limits.

Response

Returns the created API key object.

Prop

Type

Note: Additional fields may be present in the response object.

Request
curl -X POST "https://app.rybbit.io/api/user/api-keys" \
  -H "Cookie: __Secure-better-auth.session_token=YOUR_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "CI pipeline", "expiresIn": 2592000, "permissions": {"analytics": ["read"]}}'
Request
const response = await fetch(
  'https://app.rybbit.io/api/user/api-keys',
  {
    method: 'POST',
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'CI pipeline',
      expiresIn: 2592000
    })
  }
);

const data = await response.json();
Request
import requests

response = requests.post(
    'https://app.rybbit.io/api/user/api-keys',
    json={
        'name': 'CI pipeline',
        'expiresIn': 2592000
    },
    headers={
        'Cookie': '__Secure-better-auth.session_token=YOUR_SESSION_TOKEN'
    }
)

data = response.json()
Request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://app.rybbit.io/api/user/api-keys");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'name' => 'CI pipeline',
    'expiresIn' => 2592000
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Cookie: __Secure-better-auth.session_token=YOUR_SESSION_TOKEN',
    'Content-Type: application/json'
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
Request
require 'net/http'
require 'json'

uri = URI("https://app.rybbit.io/api/user/api-keys")
req = Net::HTTP::Post.new(uri)
req['Cookie'] = '__Secure-better-auth.session_token=YOUR_SESSION_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  name: 'CI pipeline',
  expiresIn: 2592000
}.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
body := bytes.NewBuffer([]byte(`{
  "name": "CI pipeline",
  "expiresIn": 2592000
}`))
req, _ := http.NewRequest("POST", "https://app.rybbit.io/api/user/api-keys", body)
req.Header.Set("Cookie", "__Secure-better-auth.session_token=YOUR_SESSION_TOKEN")
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()

var data map[string]interface{}
json.NewDecoder(resp.Body).Decode(&data)
Request
let client = reqwest::Client::new();
let res = client
    .post("https://app.rybbit.io/api/user/api-keys")
    .header("Cookie", "__Secure-better-auth.session_token=YOUR_SESSION_TOKEN")
    .json(&serde_json::json!({
        "name": "CI pipeline",
        "expiresIn": 2592000
    }))
    .send()
    .await?;

let data: serde_json::Value = res.json().await?;
Request
HttpClient client = HttpClient.newHttpClient();
String json = "{\"name\": \"CI pipeline\", \"expiresIn\": 2592000}";
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://app.rybbit.io/api/user/api-keys"))
    .header("Cookie", "__Secure-better-auth.session_token=YOUR_SESSION_TOKEN")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(json))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
Request
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Cookie", "__Secure-better-auth.session_token=YOUR_SESSION_TOKEN");

var content = new StringContent(
    "{\"name\": \"CI pipeline\", \"expiresIn\": 2592000}",
    Encoding.UTF8,
    "application/json"
);

var response = await client.PostAsync("https://app.rybbit.io/api/user/api-keys", content);
var data = await response.Content.ReadAsStringAsync();
The full key value is returned only once, at creation. Store it securely — it cannot be retrieved again.
Response
{
  "id": "key_8f3a1b2c4d5e6f7g",
  "key": "aBcDeFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "CI pipeline",
  "start": "aBcDeF",
  "prefix": null,
  "referenceId": "user_2a9b8c7d6e5f4g3h",
  "configId": "default",
  "permissions": { "analytics": ["read"] },
  "metadata": null,
  "enabled": true,
  "expiresAt": "2026-07-25T12:00:00.000Z",
  "createdAt": "2026-06-25T12:00:00.000Z",
  "updatedAt": "2026-06-25T12:00:00.000Z",
  "rateLimitEnabled": false,
  "rateLimitMax": 10,
  "rateLimitTimeWindow": 86400000
}
On Rybbit Cloud, API keys require a Standard or Pro plan; free/basic plans receive HTTP 403. Rate limits are charged to you, the owning user, and are shared by every personal key you hold across every organization you belong to — creating a key does not add budget, and a plan change applies to keys you already have. For a budget that belongs to the organization instead, create an organization key.