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
- natural
- emits
- service_account.updated
- MCP tool
- update_service_account
- decision_set
- approve, reject, edit
- REST
- POST https://api.containertradehq.com/v1/cap/update_service_account
Through MCP this call returns an approval request first; see Approvals.
Idempotency: keyed by the contract's own inputs: the same inputs replay the first call's result
Inputs
| name | type | required | validation |
|---|---|---|---|
| org_id | org_id | required | tradehq-org-id; 1 to 20 characters The org the account belongs to. |
| service_account_id | text | required | 1 to 14 characters The account to change. |
| name | text | optional | 1 to 80 characters A new name. |
| owner_user_id | user_id | optional | tradehq-user-id; 1 to 20 characters The primary owner. Naming either owner names the pair the account ends with, which must be two different active members. |
| backup_owner_user_id | user_id | optional | tradehq-user-id; 1 to 20 characters The backup owner, who takes over when the primary is deactivated. |
| role_template_id | text | optional | 1 to 64 characters A new role template: shipped or the org's own, never owner or admin. |
| expires_in_days | integer | optional | 1 to 365 Renew: the account expires this many days from now, at most 365. |
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
service_account_not_found· 422 · the org has no such service accountservice_account_disabled· 422 · the account is disabled, which is finaltwo_owners_required· 422 · reassigning owners names both: the account would be left without a primary or a backupowners_must_differ· 422 · the primary and the backup owner are the same personowner_not_active_member· 422 · an owner is deactivated or not a member of the orgrole_template_not_assignable· 422 · the role template is Owner, Admin, a guest's, or carries org.admin or role.manageunknown_role_template· 422 · the role template is neither shipped nor the org's ownpermission_not_held· 422 · the role template carries a permission the calling admin's own role does not
The platform refusals apply to every call: version, authentication, authority, validation and rate limits, each in the same envelope.
Surfaces
- Mobile: degraded: composition
- MCP: approval required
- Voice: degraded: composition
- OneBox: no document originates a service account
- Outbound: crosses to no counterparty
Events
service_account.updatedaudit_only
Related
create_api_key, create_service_account, disable_service_account