# Provision service account with roles

Source: https://business-api-docs.youhodler.com/docs/api/reference/service-accounts/service-accounts-provision

Creates a service account and grants it the supplied roles in a single call. Equivalent to `POST /service-accounts` followed by N × `POST /role-assignments`, but saves the client the round-trips. Best-effort grant phase: the service account is always created if `identity-service` accepts it; per-role grant failures are reported in `role_assignment_errors` (preserving the input order) and the response is still `201`. The plaintext `client_secret` is returned **exactly once** — store it before retrying any failed grants.

## Request

**Request URL — POST**
```http
POST /service-accounts/provision
```

**Request Body — application/json**
```json
{
  "description": "Withdrawal automation account",
  "parent_ref": "enterprises/b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
  "roles": [
    {
      "role_ref": "roles/b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
      "scope_ref": "enterprises/b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b"
    }
  ]
}
```

## Responses

**201 Resource created successfully**

Resource created successfully.

```json
{
  "client_id": "b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
  "client_secret": "cs_live_abc123placeholder",
  "client_secret_expires_at": "2026-05-01T10:00:00Z",
  "principal_ref": "service-accounts/b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
  "role_assignment_errors": [],
  "role_assignments": [],
  "service_account": {
    "description": "Withdrawal automation account",
    "created_at": "2026-05-01T10:00:00Z",
    "current_secret_expires_at": "2026-05-01T10:00:00Z",
    "etag": "W/\"sa-etag-0001\"",
    "external_id": "sa-ext-001",
    "id": "b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
    "parent_ref": "enterprises/b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
    "previous_secret_expires_at": null,
    "principal_ref": "service-accounts/b8e2f1a0-4c3d-4e5f-9a1b-2c3d4e5f6a7b",
    "resource": "service_account",
    "status": "active",
    "updated_at": "2026-05-01T10:00:00Z"
  }
}
```

**400 Invalid request payload**

Invalid request payload, query, or parameter shape.

```json
{
  "code": "invalid_request",
  "details": {
    "reason": "capability_scope_mismatch"
  },
  "message": "Request validation failed"
}
```

**401 Caller is not authenticated or the bearer token is invalid**

Caller is not authenticated or the bearer token is invalid.

```json
{
  "code": "unauthorized",
  "message": "Authentication required."
}
```

**403 Caller lacks the required capability or permitted scope**

Caller lacks the required capability or permitted scope.

```json
{
  "code": "forbidden_capability_scope",
  "details": {
    "reason": "missing_capability"
  },
  "message": "Insufficient capability for this operation."
}
```

**409 State conflict — the request cannot be applied to the current resource state**

State conflict — the request cannot be applied to the current resource state.

```json
{
  "code": "idempotency_conflict",
  "details": {
    "reason": "key_payload_mismatch"
  },
  "message": "Idempotency key already used with a different payload"
}
```

**422 Operation is not admissible — it violates a business rule**

Operation is not admissible — it violates a business rule, policy constraint, or lifecycle precondition specific to this resource.

```json
{
  "code": "not_admissible",
  "details": {
    "reason": "not_applicable"
  },
  "message": "Request is semantically invalid under current policy"
}
```

**429 Request rate limit exceeded**

Request rate limit exceeded. Retry after the delay indicated in the `details.retry_after_ms` field.

```json
{
  "code": "rate_limited",
  "details": {
    "reason": "rate_limited",
    "retry_after_ms": 5000
  },
  "message": "Too many requests — retry after the indicated delay"
}
```

**502 Upstream service returned an unexpected error**

Upstream service returned an unexpected error.

```json
{
  "code": "upstream_error",
  "message": "An upstream service returned an unexpected error."
}
```

**503 Service is temporarily unavailable**

Service is temporarily unavailable; retry with backoff.

```json
{
  "code": "temporarily_unavailable",
  "details": {
    "reason": "federation_discovery_failed"
  },
  "message": "Identity service is temporarily unavailable"
}
```
