Loading...
Loading...
Clerk Backend REST API explorer and executor. Browse tags, inspect endpoint schemas, and execute authenticated requests. Use when listing users, managing organizations, or calling any Clerk API endpoint.
npx skill4agent add midudev/autoskills clerk-backend-apiecho $CLERK_SECRET_KEY | head -c 10echo $CLERK_BAPI_SCOPES$CLERK_SECRET_KEY$USER_ID$ORG_ID$EMAIL# Step 1 — Create organization
ORG=$(curl -s -X POST "https://api.clerk.com/v1/organizations" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d "{\"name\": \"Acme Corp\", \"created_by\": \"$USER_ID\"}")
echo "$ORG" | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d, indent=2))"
# Step 2 — Extract org ID
ORG_ID=$(echo "$ORG" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
# Step 3 — Invite member with role
curl -s -X POST "https://api.clerk.com/v1/organizations/${ORG_ID}/invitations" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d "{\"email_address\": \"user@example.com\", \"role\": \"org:admin\"}" \
| python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))""org:admin""org:member"org:@clerk/nextjs@clerk/backendimport { clerkClient } from '@clerk/nextjs/server'
// OR if using @clerk/backend directly:
// import { createClerkClient } from '@clerk/backend'
// const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY })
// Step 1: Create organization
const org = await clerkClient.organizations.createOrganization({
name: 'Acme Corp',
createdBy: userId, // required — the ID of the user creating the org
})
// Step 2: Invite member to the org
const invitation = await clerkClient.organizations.createOrganizationInvitation({
organizationId: org.id,
emailAddress: 'user@example.com',
role: 'org:admin', // or 'org:member'
})| Type | Field | Readable by | Writable by | Use for |
|---|---|---|---|---|
| Public | | Client + Server | Server only | Plan tier, roles, feature flags the frontend reads |
| Private | | Server only | Server only | Stripe IDs, compliance flags, internal identifiers |
| Unsafe | | Client + Server | Client + Server | Ephemeral UI state, onboarding steps (client-writable — avoid sensitive data) |
plan: 'pro'onboarded: truepublic_metadatacurl -s -X PATCH "https://api.clerk.com/v1/users/${USER_ID}" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"public_metadata": {"plan": "pro", "onboarded": true}}' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(f'Updated user {d[\"id\"]}: public_metadata={d.get(\"public_metadata\")}')"import { clerkClient } from '@clerk/nextjs/server'
// OR: import { createClerkClient } from '@clerk/backend'
await clerkClient.users.updateUser(userId, {
publicMetadata: { plan: 'pro', onboarded: true }, // readable by client, writable server-only
// privateMetadata: { stripeId: 'cus_xxx' }, // server-only read AND write
// unsafeMetadata: { step: 'welcome' }, // client-writable, avoid sensitive data
})snake_casepublic_metadatacamelCasepublicMetadatacurl -s "https://api.clerk.com/v1/users?limit=100&offset=0&order_by=-created_at&created_at=gt:$(date -d '7 days ago' +%s 2>/dev/null || date -v-7d +%s)000" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
if isinstance(data, list):
print(f'Found {len(data)} users:')
for u in data:
print(f' {u[\"id\"]}: {u.get(\"email_addresses\", [{}])[0].get(\"email_address\", \"no email\")}')
else:
print(json.dumps(data, indent=2))
"# ONLY run after explicit user confirmation
curl -s -X DELETE "https://api.clerk.com/v1/users/${USER_ID}" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(f'Deleted: {d}')"https://api.clerk.com/v1Authorization: Bearer $CLERK_SECRET_KEYGET /v1/users
Query params: limit (max 500, default 10), offset, order_by (+/-created_at, +/-updated_at, +/-email_address, +/-web3wallet, +/-first_name, +/-last_name, +/-phone_number, +/-username, +/-last_active_at, +/-last_sign_in_at), email_address[], phone_number[], username[], web3wallet[], user_id[], query, created_at (ISO 8601 range: gt:TIMESTAMP or lt:TIMESTAMP in Unix ms)
Returns: array of User objectsGET /v1/users/{user_id}
Returns: User objectPATCH /v1/users/{user_id}
Body (JSON, snake_case): { public_metadata, private_metadata, unsafe_metadata, first_name, last_name, username, ... }DELETE /v1/users/{user_id}
Destroys: user record, all sessions, all memberships, all associated data
Returns: { id, object, deleted: true }POST /v1/organizations
Body: { name: string, created_by: string (user_id), public_metadata?, private_metadata?, max_allowed_memberships? }
Returns: Organization object with { id, name, slug, ... }GET /v1/organizations
Query params: limit, offset, query, order_byPOST /v1/organizations/{organization_id}/invitations
Body: { email_address: string, role: string ("org:admin" or "org:member"), public_metadata?, private_metadata? }
Returns: OrganizationInvitation objectcurlapi-specs-context.shextract-tags.jsextract-endpoint-detail.shcurlscripts/execute-request.shcurl -s "https://api.clerk.com/v1${PATH}${QUERY_STRING}" \
-H "Authorization: Bearer $CLERK_SECRET_KEY"curl -s -X ${METHOD} "https://api.clerk.com/v1${PATH}" \
-H "Authorization: Bearer $CLERK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '${BODY_JSON}'curl -s -X DELETE "https://api.clerk.com/v1${PATH}" \
-H "Authorization: Bearer $CLERK_SECRET_KEY"python3 -c "import sys,json; data=json.load(sys.stdin); print(json.dumps(data, indent=2))"bash scripts/api-specs-context.shplatformCLERK_BAPI_SCOPESlimitoffsetscripts/execute-request.sh| Environment | Limit |
|---|---|
| Production | 1,000 requests / 10 seconds |
| Development | 100 requests / 10 seconds |
| Single invitations | 100 / hour |
| Bulk invitations | 25 / hour |
| Org invitations | 250 / hour |
| Frontend API sign-in creation | 5 / 10 seconds |
| Frontend API sign-in attempts | 3 / 10 seconds |
| List users max per page | 500 |
currentUser()auth()updateUser({ publicMetadata: { role: 'admin' } })await clerkClient.users.updateUser(userId, { publicMetadata: { newField: 'value' } })publicMetadataconst user = await clerkClient.users.getUser(userId)
await clerkClient.users.updateUser(userId, {
publicMetadata: { ...user.publicMetadata, newField: 'value' },
})| Mode | Trigger | Behavior |
|---|---|---|
| Prompt is empty, or contains only | Print usage examples (step 0) |
| Prompt is | List all tags or endpoints for a tag |
| Specific endpoint (e.g. | Look up endpoint, execute request |
| Endpoint + | Show endpoint schema, don't execute |
--version 2024-10-01helpbrowseexecutedetailBrowse
/clerk-backend-api tags — list all tags
/clerk-backend-api Users — browse endpoints for the Users tag
/clerk-backend-api Users version 2025-11-10.yml — browse using a different version
Execute
/clerk-backend-api GET /users — fetch all users
/clerk-backend-api get user john_doe — natural language works too
/clerk-backend-api POST /invitations — create an invitation
Inspect
/clerk-backend-api GET /users help — show endpoint schema without executing
/clerk-backend-api POST /invitations -h — view request/response details
Options
--admin — bypass scope restrictions for write/delete
--version [date], version [date] — use a specific spec version
--help, -h, help — inspect endpoint instead of executingbrowsetagshelpexecutedetailcurl -s https://raw.githubusercontent.com/clerk/openapi-specs/main/bapi/${version_name} | node scripts/extract-tags.jsbrowsehelpexecutedetailcurl -s https://raw.githubusercontent.com/clerk/openapi-specs/main/bapi/${version_name} | bash scripts/extract-tag-endpoints.sh "${tag_name}"executedetailhelpbrowseexecutecurl -s https://raw.githubusercontent.com/clerk/openapi-specs/main/bapi/${version_name} | bash scripts/extract-endpoint-detail.sh "${path}" "${method}"${path}/users/{user_id}${method}getdetailexecuteexecutescripts/execute-request.shRESPONSE=$(curl -s "https://api.clerk.com/v1/users?limit=10" \
-H "Authorization: Bearer $CLERK_SECRET_KEY")
echo "$RESPONSE" | python3 -c "
import sys, json
data = json.load(sys.stdin)
if isinstance(data, list):
print(f'Found {len(data)} users:')
for u in data:
print(f' {u[\"id\"]}: {u.get(\"email_addresses\", [{}])[0].get(\"email_address\", \"no email\")}')
else:
print(json.dumps(data, indent=2))
"clerk-setupclerk-orgsclerk-webhooks