Create an API key. The secret is returned once.
POST
/api/v1/workspaces/{workspaceId}/api-keys
const url = 'https://api.crossmart.io/api/v1/workspaces/example/api-keys';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"role":"OWNER","customRoleId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","name":"Claude Desktop","expiresAt":"2026-04-15T12:00:00Z"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.crossmart.io/api/v1/workspaces/example/api-keys \ --header 'Content-Type: application/json' \ --data '{ "role": "OWNER", "customRoleId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "Claude Desktop", "expiresAt": "2026-04-15T12:00:00Z" }'Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”workspaceId
required
string
Request Bodyrequired
Section titled “Request Bodyrequired”Media typeapplication/json
object
role
required
At most your own access. CUSTOM needs customRoleId.
string
customRoleId
One of the workspace’s roles, with CUSTOM
string format: uuid
name
required
string
Example
Claude DesktopexpiresAt
Leave empty for a key that does not expire
string format: date-time
Responses
Section titled “Responses”Media typeapplication/json
object
apiKey
required
object
id
required
string format: uuid
name
required
string
role
required
string
customRole
required
The workspace’s own role, when role is CUSTOM
object
id
required
string format: uuid
name
required
string
prefix
required
The first characters of the key, to tell keys apart
string
lastUsedAt
required
string format: date-time
expiresAt
required
string format: date-time
createdAt
required
string format: date-time
secret
required
The full key. Shown once; store it now.
string
Example
{ "apiKey": { "role": "OWNER" }}The organization’s plan does not allow this (ENTITLEMENTS_ENFORCED is on). code and feature say why; upgrading the plan resolves it.
Media typeapplication/json
object
statusCode
required
number
error
required
string
code
required
string
message
required
string
feature
required
string
plan
required
The code of the organization’s plan
string
limit
required
Null is unlimited
number
usage
required
number
requested
required
How many more the request asked for
number
Example
{ "statusCode": 402, "error": "Payment Required", "code": "plan_limit_reached", "message": "The Free plan includes 2 connected channels, and 2 are in use. Upgrade the plan to add more.", "feature": "active_listings", "plan": "free"}