Create API Key
curl --request POST \
--url https://api.signa.so/v1/organization/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"scopes": [
"<string>"
],
"expires_at": {},
"metadata": {}
}
'import requests
url = "https://api.signa.so/v1/organization/api-keys"
payload = {
"name": "<string>",
"scopes": ["<string>"],
"expires_at": {},
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', scopes: ['<string>'], expires_at: {}, metadata: {}})
};
fetch('https://api.signa.so/v1/organization/api-keys', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/organization/api-keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'scopes' => [
'<string>'
],
'expires_at' => [
],
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/organization/api-keys"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"scopes\": [\n \"<string>\"\n ],\n \"expires_at\": {},\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/organization/api-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"scopes\": [\n \"<string>\"\n ],\n \"expires_at\": {},\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/organization/api-keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"scopes\": [\n \"<string>\"\n ],\n \"expires_at\": {},\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "key_Pe5hI9jK",
"object": "api_key",
"name": "Aurora Digital analytics",
"key": "sig_69f99181efdb8d205c86878c5f232ee0722f22750b2cc25b",
"prefix": "sig_69f99181",
"scopes": ["trademarks:read", "billing:read"],
"rate_limit_tier": "standard",
"status": "active",
"expires_at": null,
"last_used_at": null,
"metadata": {},
"revoked_at": null,
"created_by": "key_Mc2eF6gH",
"created_at": "2026-06-12T16:00:00.000Z",
"updated_at": "2026-06-12T16:00:00.000Z",
"request_id": "req_wP2gH8iJ"
}
API Keys
Create API Key
Generate a new API key for the organization
POST
/
v1
/
organization
/
api-keys
Create API Key
curl --request POST \
--url https://api.signa.so/v1/organization/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"scopes": [
"<string>"
],
"expires_at": {},
"metadata": {}
}
'import requests
url = "https://api.signa.so/v1/organization/api-keys"
payload = {
"name": "<string>",
"scopes": ["<string>"],
"expires_at": {},
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', scopes: ['<string>'], expires_at: {}, metadata: {}})
};
fetch('https://api.signa.so/v1/organization/api-keys', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/organization/api-keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'scopes' => [
'<string>'
],
'expires_at' => [
],
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/organization/api-keys"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"scopes\": [\n \"<string>\"\n ],\n \"expires_at\": {},\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/organization/api-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"scopes\": [\n \"<string>\"\n ],\n \"expires_at\": {},\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/organization/api-keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"scopes\": [\n \"<string>\"\n ],\n \"expires_at\": {},\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "key_Pe5hI9jK",
"object": "api_key",
"name": "Aurora Digital analytics",
"key": "sig_69f99181efdb8d205c86878c5f232ee0722f22750b2cc25b",
"prefix": "sig_69f99181",
"scopes": ["trademarks:read", "billing:read"],
"rate_limit_tier": "standard",
"status": "active",
"expires_at": null,
"last_used_at": null,
"metadata": {},
"revoked_at": null,
"created_by": "key_Mc2eF6gH",
"created_at": "2026-06-12T16:00:00.000Z",
"updated_at": "2026-06-12T16:00:00.000Z",
"request_id": "req_wP2gH8iJ"
}
Overview
Creates a new API key for your organization. The full key secret is returned only once in the response; it cannot be retrieved again. Store it securely immediately after creation. You can assign a name for identification, specific scopes to limit access, an optional expiration date, and key-value metadata. You cannot grant scopes the calling key does not itself hold, and an organization can have at most 25 active keys. Requires theapi-keys:manage scope. This endpoint requires an Idempotency-Key header; see Idempotency.
Request Body
string
required
Human-readable name for the key, 1-255 characters (e.g. “Production Backend”).
string[]
required
Authorized scopes (1-20 values, must be a subset of the calling key’s scopes):
| Scope | Grants access to |
|---|---|
trademarks:read | Trademark records, owners, attorneys, firms, proceedings — all public catalog data |
events:read | Internal-tagged, held event feed (/v1/events). Plan-gated. alert.created is projected; trademark.* is projected for portfolio marks when the projector is enabled. portfolio_id filters every family through the event-time membership snapshot. |
portfolios:manage | Customer-owned resources: portfolios, watches, alerts, webhooks |
api-keys:manage | API key creation, rotation, update, and revocation |
organization:manage | Organization settings (e.g. renaming the organization) |
billing:read | Usage, plan, and request log endpoints |
string | null
Optional ISO 8601 timestamp for key expiration. Must be in the future. Omit or pass
null for a non-expiring key.object
Optional key-value metadata (string values, max 50 keys).
Response
Returns the full API key object plus the one-timekey secret, flat at the top level.
string
Key ID (
key_*).string
Always
api_key.string
Key name.
string
Full API key secret. This is the only time it is returned.
string
First 12 characters of the key, for identification.
string[]
Authorized scopes.
string
Rate limit tier label for the key.
standard by default.string
Lifecycle state:
active, expired, or revoked. Always active on creation.string | null
Expiry timestamp, or
null.string | null
Always
null on creation.object
Key-value metadata.
string | null
Always
null on creation.string
ID of the API key that created this key.
string
Creation timestamp.
string
Last update timestamp.
string
Unique request identifier for support and debugging.
{
"id": "key_Pe5hI9jK",
"object": "api_key",
"name": "Aurora Digital analytics",
"key": "sig_69f99181efdb8d205c86878c5f232ee0722f22750b2cc25b",
"prefix": "sig_69f99181",
"scopes": ["trademarks:read", "billing:read"],
"rate_limit_tier": "standard",
"status": "active",
"expires_at": null,
"last_used_at": null,
"metadata": {},
"revoked_at": null,
"created_by": "key_Mc2eF6gH",
"created_at": "2026-06-12T16:00:00.000Z",
"updated_at": "2026-06-12T16:00:00.000Z",
"request_id": "req_wP2gH8iJ"
}
Code Examples
curl -X POST "https://api.signa.so/v1/organization/api-keys" \
-H "Authorization: Bearer sig_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-analytics-key-2026-06-12" \
-d '{
"name": "Aurora Digital analytics",
"scopes": ["trademarks:read", "billing:read"]
}'
import { Signa } from "@signa-so/sdk";
const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });
const apiKey = await signa.organization.apiKeys.create({
name: "Aurora Digital analytics",
scopes: ["trademarks:read", "billing:read"],
});
// Store apiKey.key securely: it won't be returned again
console.log("New key:", apiKey.key);
Errors
| Status | Type | Description |
|---|---|---|
| 400 | validation_error | Missing name, unknown scope values, invalid expires_at, or missing Idempotency-Key header |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | API key lacks api-keys:manage, or the request grants scopes the calling key does not hold |
| 409 | conflict | The Idempotency-Key was already used with a different request body |
| 409 | idempotency_processing | A request with the same Idempotency-Key is still in flight |
| 429 | rate_limited | Too many requests, or the organization already has 25 active keys |
Retrying with the same
Idempotency-Key and the same body replays the cached response, including the same key secret, so an ambiguous network failure never mints a second credential. Duplicate key names are allowed and do not 409.Related Endpoints
- List API Keys, view all keys
- Rotate API Key, rotate an existing key
- Get Current Organization, organization profile