create_service_account

Create a service account

act entity tenant-private since 2026-10-01

Makes a service account on an org: a non-human principal that owns API keys and acts under its own role template. It has a primary and a backup owner, two different active members of the org; when the primary is deactivated the backup takes over, and when the last owner is deactivated the account is suspended until an admin reassigns it. Its role template is never Owner or Admin. It expires after expires_in_days (at most 365) unless renewed, and its mode, live or test, is the mode of every key it holds. Issue its keys with create_api_key.

Contract

shape
entity
authority
act
evidence
none
subscription
false
permission
any one of: org.admin (carried by the caller's role template in the org `org_id`); account.owner (account role owner or higher in the account of the org `org_id`); a deactivated caller is refused first
idempotency
keyed
emits
service_account.created
MCP tool
create_service_account
decision_set
approve, reject
REST
POST https://api.containertradehq.com/v1/cap/create_service_account

Through MCP this call returns an approval request first; see Approvals.

Idempotency: keyed by the caller's Idempotency-Key, which is required: the same key and inputs replay the first result, the same key with other inputs is 409 idempotency_key_reused

Inputs

nametyperequiredvalidation
org_idorg_idrequiredtradehq-org-id; 1 to 20 characters
The live org the account belongs to.
nametextrequired1 to 80 characters
What the account is for, such as the integration that holds its keys.
owner_user_iduser_idrequiredtradehq-user-id; 1 to 20 characters
The primary owner: an active member of the org.
backup_owner_user_iduser_idrequiredtradehq-user-id; 1 to 20 characters
The backup owner: another active member of the org, who takes over when the primary is deactivated.
role_template_idtextrequired1 to 64 characters
The role template the account acts under: a shipped one or the org's own, never owner or admin.
expires_in_daysintegeroptional1 to 365; default 365
Days until the account and every key of it stop working, at most 365 (the default). update_service_account renews it.
modeone_ofoptionalone of live, test
live (the default) or test. Its keys are sk_live_ or sk_test_ to match; it never changes.

Response

  • service_account_id · string · The account's id.
  • org_id · string · The live org it belongs to.
  • name · string · What it is for.
  • owner_user_id · stringnull · Its primary owner; null only while it is suspended for want of one.
  • backup_owner_user_id · stringnull · Its backup owner, who takes over when the primary is deactivated; null once that has happened.
  • role_template_id · string · The role template it acts under: never Owner or Admin.
  • mode · string · live or test; its keys are sk_live_ or sk_test_ to match.
  • status · string · active; suspended when its last owner was deactivated, until an admin reassigns it; disabled, which is final; or expired.
  • expires_at · string · When it and every key of it stop working, unless renewed.
  • keys · integer · How many working keys it holds.
  • last_used_at · stringnull · The start of the last minute any key of it was served a request; null if never.
  • created_at · string · When it was made.
  • created_by · string · Who made it.
Full JSON Schema
{
  "type": "object",
  "properties": {
    "service_account_id": {
      "type": "string",
      "description": "The account's id.",
      "x-data-class": "operational"
    },
    "org_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 20,
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "format": "tradehq-org-id",
      "description": "The live org it belongs to.",
      "x-data-class": "operational"
    },
    "name": {
      "type": "string",
      "description": "What it is for.",
      "x-data-class": "operational"
    },
    "owner_user_id": {
      "type": [
        "string",
        "null"
      ],
      "minLength": 1,
      "maxLength": 20,
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "format": "tradehq-user-id",
      "description": "Its primary owner; null only while it is suspended for want of one.",
      "x-data-class": "operational"
    },
    "backup_owner_user_id": {
      "type": [
        "string",
        "null"
      ],
      "minLength": 1,
      "maxLength": 20,
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "format": "tradehq-user-id",
      "description": "Its backup owner, who takes over when the primary is deactivated; null once that has happened.",
      "x-data-class": "operational"
    },
    "role_template_id": {
      "type": "string",
      "description": "The role template it acts under: never Owner or Admin.",
      "x-data-class": "operational"
    },
    "mode": {
      "type": "string",
      "enum": [
        "live",
        "test"
      ],
      "description": "live or test; its keys are sk_live_ or sk_test_ to match.",
      "x-data-class": "operational"
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "suspended",
        "disabled",
        "expired"
      ],
      "description": "active; suspended when its last owner was deactivated, until an admin reassigns it; disabled, which is final; or expired.",
      "x-data-class": "operational"
    },
    "expires_at": {
      "type": "string",
      "format": "date-time",
      "description": "When it and every key of it stop working, unless renewed.",
      "x-data-class": "operational"
    },
    "keys": {
      "type": "integer",
      "description": "How many working keys it holds.",
      "x-data-class": "operational"
    },
    "last_used_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "The start of the last minute any key of it was served a request; null if never.",
      "x-data-class": "operational"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "When it was made.",
      "x-data-class": "operational"
    },
    "created_by": {
      "type": "string",
      "minLength": 1,
      "maxLength": 20,
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "format": "tradehq-user-id",
      "description": "Who made it.",
      "x-data-class": "operational"
    }
  },
  "required": [
    "service_account_id",
    "org_id",
    "name",
    "owner_user_id",
    "backup_owner_user_id",
    "role_template_id",
    "mode",
    "status",
    "expires_at",
    "keys",
    "last_used_at",
    "created_at",
    "created_by"
  ],
  "additionalProperties": false
}

Refusals

The platform refusals apply to every call: version, authentication, authority, validation and rate limits, each in the same envelope.

Surfaces

DesktopF
MobileD5
APIF
MCPF*
VoiceD5
PushF
OneBoxN
OutboundN
  • Mobile: degraded: composition
  • MCP: approval required
  • Voice: degraded: composition
  • OneBox: no document originates a service account
  • Outbound: crosses to no counterparty

Events

Related

create_api_key, get_api_usage, get_view_default, list_saved_views, save_view, set_my_view_default, set_org_view_default, update_service_account