create-service-account
dci create-service-account [body] [flags]
Creates a service account owned by the authenticated customer. It cannot authenticate anything until it has an API token; mint one with the api-tokens sub-resource. Returns 409 when another service account of the customer already uses name. With dryRun=true the request goes through the same checks as a real create (name bounds and uniqueness, permission names, caller scope) and returns the same errors without creating anything. When the caller authenticates with a service account token, createdBy, createdByEmail and createdByUserId are null. Requires the serviceAccountCreator permission.
Pass the request body as name: value arguments or pipe JSON on stdin — see Command structure.
Only name is required (1-100 characters, no leading or trailing whitespace, unique among
the customer's service accounts, 409 otherwise). An unknown permission name returns 422.
Requires the serviceAccountCreator permission.
A new service account cannot authenticate anything until it has an API token: mint one with
dci create-service-account-token. The API requires an Idempotency-Key on every real
call; retrying with the same key and request returns the stored response (keys are kept for
24 hours).
--dry-run sends the request with the API's dryRun=true: it runs the same checks as a real
create (name bounds and uniqueness, permission names, caller scope) and returns the same
errors without creating anything. In the response, id, createTime, updateTime and
etag are null.
Examples
# Create a service account with a set of permissions (camelCase names, as in the Console role editor).
dci create-service-account name: terraform-ci, description: "Manages DoiT resources from CI", permissions: [cloudAnalyticsReadOnly, budgetsManager] --idempotency-key "$(uuidgen)"
# Check the request server-side first; nothing is created and the CLI supplies a throwaway idempotency key.
dci create-service-account name: terraform-ci, permissions: [cloudAnalyticsReadOnly] --dry-run
# Create it from a JSON file and capture the new ID, to mint its first API token next.
dci create-service-account --idempotency-key "$(uuidgen)" --output json < service-account.json | jq -r .id
# service-account.json
{"name": "terraform-ci", "description": "Manages DoiT resources from CI",
"permissions": ["cloudAnalyticsReadOnly", "budgetsManager"]}
Request
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Name, unique among the customer's service accounts. Leading or trailing whitespace returns 400. |
description | string | Free-text description. | |
permissions | array of string | Platform permission names in camelCase, for example cloudAnalyticsReadOnly. An unknown name returns 422. |
Example body (JSON)
{
"name": "terraform-ci",
"description": "Manages DoiT resources from CI",
"permissions": [
"cloudAnalyticsReadOnly",
"budgetsManager"
]
}
Raw JSON schema
{
"type": "object",
"description": "Fields of a new service account.",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "Name, unique among the customer's service accounts. Leading or trailing whitespace returns `400`.",
"example": "terraform-ci"
},
"description": {
"type": "string",
"description": "Free-text description.",
"example": "Manages DoiT resources from CI"
},
"permissions": {
"type": "array",
"description": "Platform permission names in camelCase, for example `cloudAnalyticsReadOnly`. An unknown name returns `422`.",
"items": {
"type": "string"
}
}
}
}
Flags
| Flag | Type | Default | Example | Description |
|---|---|---|---|---|
--dry-run | boolean | false | If true, validates the request and returns the would-be result without applying it. The response then carries the X-Dry-Run header. |
Every command also accepts the CLI-wide flags for output shaping — see Output formats and Table output options.
Output
OK - Dry run only (dryRun=true). Every check of a real create passed and nothing was created; id, createTime, updateTime and etag are null.
By default dci renders the result as a table. Use --output json to get the full structure described below — see Output formats.
| Field | Type | Description |
|---|---|---|
id | string | Service account ID. null only on a dry-run create. |
customerId | string | ID of the customer that owns the service account. |
name | string | Name, unique among the customer's service accounts. |
description | string | Free-text description. |
permissions | array of string | Platform permission names in camelCase, as shown in the DoiT console role editor. |
createdBy | string | Display name of the user who created the service account. null when unknown or when the service account was created with a service account token. |
createdByEmail | string | Email of the user who created the service account. null when unknown or when the service account was created with a service account token. |
createdByUserId | string | ID of the user who created the service account. null when unknown or when the service account was created with a service account token. |
createTime | string (date-time) | When the service account was created. |
updateTime | string (date-time) | When the service account was last changed. |
etag | string | Current version of the service account. Send it in If-Match to update or delete. |
Example response (--output json)
{
"id": null,
"customerId": "Kp2mN8qL4vR0sT1wX3yZ",
"name": "terraform-ci",
"description": "Manages DoiT resources from CI",
"permissions": [
"cloudAnalyticsReadOnly",
"budgetsManager"
],
"createdBy": null,
"createdByEmail": null,
"createdByUserId": null,
"createTime": null,
"updateTime": null,
"etag": null
}
Raw JSON schema
{
"type": "object",
"description": "A non-human identity owned by a customer. Its API tokens authenticate with exactly the permissions listed here.",
"required": [
"id",
"customerId",
"name",
"description",
"permissions",
"createdBy",
"createdByEmail",
"createdByUserId",
"createTime",
"updateTime",
"etag"
],
"properties": {
"id": {
"type": "string",
"nullable": true,
"readOnly": true,
"description": "Service account ID. `null` only on a dry-run create.",
"example": "Lq3nO9rM5wS2tU0xY4zA"
},
"customerId": {
"type": "string",
"readOnly": true,
"description": "ID of the customer that owns the service account.",
"example": "Kp2mN8qL4vR0sT1wX3yZ"
},
"name": {
"type": "string",
"description": "Name, unique among the customer's service accounts."
},
"description": {
"type": "string",
"description": "Free-text description."
},
"permissions": {
"type": "array",
"description": "Platform permission names in camelCase, as shown in the DoiT console role editor.",
"items": {
"type": "string"
}
},
"createdBy": {
"type": "string",
"nullable": true,
"readOnly": true,
"description": "Display name of the user who created the service account. `null` when unknown or when the service account was created with a service account token."
},
"createdByEmail": {
"type": "string",
"nullable": true,
"readOnly": true,
"description": "Email of the user who created the service account. `null` when unknown or when the service account was created with a service account token."
},
"createdByUserId": {
"type": "string",
"nullable": true,
"readOnly": true,
"description": "ID of the user who created the service account. `null` when unknown or when the service account was created with a service account token."
},
"createTime": {
"type": "string",
"format": "date-time",
"nullable": true,
"readOnly": true,
"description": "When the service account was created."
},
"updateTime": {
"type": "string",
"format": "date-time",
"nullable": true,
"readOnly": true,
"description": "When the service account was last changed."
},
"etag": {
"type": "string",
"nullable": true,
"readOnly": true,
"description": "Current version of the service account. Send it in `If-Match` to update or delete."
}
}
}
Errors
On failure, dci prints a single error message — with a hint when one is available — and exits with a typed code your scripts can branch on. See Errors and exit codes for the full contract.
HTTP status to exit code mapping
| HTTP status | Exit code | Error code | Meaning |
|---|---|---|---|
| 400, 422 | 30 | VALIDATION_ERROR | The arguments or request body were rejected. Review the command's flags and payload. |
| 401 | 10 | AUTHENTICATION_FAILED | Not signed in, or the API token is invalid. Run dci login or check DCI_API_KEY. |
| 403 | 11 | PERMISSION_DENIED | The DoiT user or the active customer context does not have access. |
| 409 | 21 | RESOURCE_CONFLICT | The operation conflicts with the resource's current state. |
| 500 | 40 | API_SERVER_ERROR | The API failed to process the request. Retryable; contact DoiT support if it persists. |
Related
- list-service-accounts — List service accounts
- get-service-account — Get a service account
- update-service-account — Update a service account
- create-service-account-token — Create an API token for a service account
- delete-service-account — Delete a service account
- API reference: POST /iam/v1/service-accounts
Aliases: createserviceaccount