openapi: 3.2.0 info: title: Dependency Track Service Accounts API version: 2.0.0 contact: name: The Dependency-Track Authors url: https://github.com/DependencyTrack/dependency-track email: dependencytrack@owasp.org license: name: Apache-2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html description: 'Operations tagged Service Accounts across 2 of this provider''s published API definitions: dependency-track-openapi-v2.yaml, dependency-track-v2-openapi.yml. Each path carries the servers of the definition it was published in.' servers: - url: /api/v2 security: - apiKeyAuth: [] - bearerAuth: [] tags: - name: Service Accounts description: Endpoints related to service accounts paths: /service-accounts: get: tags: - Service Accounts summary: List service accounts description: 'Returns a paginated list of service accounts, ordered by name. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_READ` permission.' operationId: listServiceAccounts parameters: - name: q in: query description: Optional search text to filter service accounts by. Filtering uses case-insensitive "contains" semantics on the name. schema: maxLength: 59 type: string - name: page_token in: query description: Opaque token pointing to a specific position in a collection schema: type: string - name: limit in: query description: Maximum number of items to retrieve from the collection schema: maximum: 1000 minimum: 1 type: integer format: int32 default: 100 responses: '200': description: Paginated list of service accounts content: application/json: schema: $ref: '#/components/schemas/list-service-accounts-response' '400': $ref: '#/components/responses/invalid-request-error' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' default: $ref: '#/components/responses/generic-error' post: tags: - Service Accounts summary: Create a service account description: 'Creates a new service account. The account''s username is the given name, prefixed with `svc:`. A new service account has no permissions and no team memberships. Grant those through the REST API v1 endpoints `POST /api/v1/{permission}/user/{username}` and `PUT /api/v1/user/membership`. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_CREATE` permission.' operationId: createServiceAccount requestBody: content: application/json: schema: $ref: '#/components/schemas/create-service-account-request' required: true responses: '201': description: Service account created headers: Location: description: URL of the created service account schema: type: string format: uri '400': $ref: '#/components/responses/invalid-request-error' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '409': $ref: '#/components/responses/generic-conflict-error' default: $ref: '#/components/responses/generic-error' servers: - url: /api/v2 /service-accounts/{name}: get: tags: - Service Accounts summary: Get a service account description: 'Returns details about a service account. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_READ` permission.' operationId: getServiceAccount parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' responses: '200': description: The service account content: application/json: schema: $ref: '#/components/schemas/get-service-account-response' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' delete: tags: - Service Accounts summary: Delete a service account description: 'Deletes a service account. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_DELETE` permission.' operationId: deleteServiceAccount parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' responses: '204': description: Service account deleted '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' patch: tags: - Service Accounts summary: Update a service account description: 'Updates a service account. Suspending an account stops its API keys from authenticating immediately. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_UPDATE` permission.' operationId: updateServiceAccount parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' requestBody: content: application/json: schema: $ref: '#/components/schemas/update-service-account-request' required: true responses: '204': description: Service account updated '400': $ref: '#/components/responses/invalid-request-error' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' servers: - url: /api/v2 /service-accounts/{name}/api-keys: get: tags: - Service Accounts summary: List the API keys of a service account description: 'Returns a paginated list of the API keys a service account owns, newest first. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_READ` permission.' operationId: listServiceAccountApiKeys parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' - name: page_token in: query description: Opaque token pointing to a specific position in a collection schema: type: string - name: limit in: query description: Maximum number of items to retrieve from the collection schema: maximum: 1000 minimum: 1 type: integer format: int32 default: 100 responses: '200': description: Paginated list of API keys content: application/json: schema: $ref: '#/components/schemas/list-service-account-api-keys-response' '400': $ref: '#/components/responses/invalid-request-error' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' post: tags: - Service Accounts summary: Create an API key for a service account description: 'Creates a new API key owned by the given service account. The plain text key is returned exactly once, in the response body. It cannot be retrieved afterwards, because only its hash is stored. No API keys can be created for a suspended service account. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_CREATE` permission.' operationId: createServiceAccountApiKey parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' requestBody: content: application/json: schema: $ref: '#/components/schemas/create-service-account-api-key-request' required: true responses: '201': description: API key created headers: Location: description: URL of the created API key schema: type: string format: uri content: application/json: schema: $ref: '#/components/schemas/create-service-account-api-key-response' '400': description: Bad Request content: application/problem+json: schema: anyOf: - $ref: '#/components/schemas/invalid-request-problem-details' - $ref: '#/components/schemas/problem-details' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' '409': $ref: '#/components/responses/generic-conflict-error' default: $ref: '#/components/responses/generic-error' servers: - url: /api/v2 /service-accounts/{name}/api-keys/{public_id}: delete: tags: - Service Accounts summary: Delete an API key of a service account description: 'Deletes a single API key owned by the given service account. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_DELETE` permission.' operationId: deleteServiceAccountApiKey parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' - name: public_id in: path description: The public ID of the API key required: true schema: maxLength: 8 type: string responses: '204': description: API key deleted '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' servers: - url: /api/v2 /service-accounts/{name}/workload-identity-bindings: get: tags: - Service Accounts summary: List the workload identity bindings of a service account description: 'Returns a paginated list of the workload identity bindings for a service account, ordered by provider name and subject. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_READ` permission.' operationId: listServiceAccountWorkloadIdentityBindings parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' - name: page_token in: query description: Opaque token pointing to a specific position in a collection schema: type: string - name: limit in: query description: Maximum number of items to retrieve from the collection schema: maximum: 1000 minimum: 1 type: integer format: int32 default: 100 responses: '200': description: Paginated list of workload identity bindings content: application/json: schema: $ref: '#/components/schemas/list-workload-identity-bindings-response' '400': $ref: '#/components/responses/invalid-request-error' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' post: tags: - Service Accounts summary: Create a workload identity binding for a service account description: 'Creates a workload identity binding for a service account. A trailing `*` in `subject` makes it a prefix match, for example `repo:acme/app:*`. For `SPIFFE` providers, the prefix must end with `/`. For multi-tenant issuers like GitHub and GitLab, ensure that the prefix contains *at least* your organization to prevent cross-tenant abuse. For example: ```json { "provider_name": "github-actions", "subject": "repo:acme-inc/*" } ``` To match a prefix within a name, add a `condition` such as `claims.sub.startsWith("repo:acme/app-")`. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_CREATE` permission.' operationId: createServiceAccountWorkloadIdentityBinding parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' requestBody: content: application/json: schema: $ref: '#/components/schemas/create-workload-identity-binding-request' required: true responses: '201': description: Workload identity binding created headers: Location: description: URL of the created workload identity binding schema: type: string format: uri content: application/json: schema: $ref: '#/components/schemas/create-workload-identity-binding-response' '400': description: Bad Request content: application/problem+json: schema: anyOf: - $ref: '#/components/schemas/invalid-cel-expression-problem-details' - $ref: '#/components/schemas/invalid-request-problem-details' - $ref: '#/components/schemas/problem-details' '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' servers: - url: /api/v2 /service-accounts/{name}/workload-identity-bindings/{binding_id}: delete: tags: - Service Accounts summary: Delete a workload identity binding of a service account description: 'Deletes a service account''s workload identity binding. Sessions already created stay valid until they expire. Requires the `ACCESS_MANAGEMENT` or `ACCESS_MANAGEMENT_DELETE` permission.' operationId: deleteServiceAccountWorkloadIdentityBinding parameters: - name: name in: path description: The name of the service account, without the `svc:` prefix required: true schema: $ref: '#/components/schemas/service-account-name' - name: binding_id in: path description: The identifier of the workload identity binding required: true schema: type: string format: uuid responses: '204': description: Workload identity binding deleted '401': $ref: '#/components/responses/generic-unauthorized-error' '403': $ref: '#/components/responses/generic-forbidden-error' '404': $ref: '#/components/responses/generic-not-found-error' default: $ref: '#/components/responses/generic-error' servers: - url: /api/v2 components: schemas: paginated-response: required: - total type: object properties: next_page_token: type: string description: Token to retrieve the next page. Absent when no more items exist. total: $ref: '#/components/schemas/total-count' x-parent: true constraint-violation-error: required: - message type: object properties: path: type: string description: Path to the invalid field in the request value: type: string description: The invalid value message: type: string description: Message explaining the error workload-identity-binding: required: - created_at - provider_name - subject - uuid type: object properties: uuid: type: string description: The identifier of the binding. format: uuid provider_name: maxLength: 63 type: string description: The name of the workload identity provider the binding belongs to. example: github-actions subject: maxLength: 512 pattern: ^[^*]+(?:[:/]\*)?$ type: string description: The `sub` claim the binding matches. A trailing `*` makes it a prefix match. example: repo:acme/app:* condition: maxLength: 2048 type: string description: A CEL expression over the token's claims that must evaluate to `true`. Absent when the binding matches on the subject alone. example: claims.ref == "refs/heads/main" created_at: $ref: '#/components/schemas/timestamp' last_used_at: description: When a token was last exchanged through the binding. Absent when it was never used. allOf: - $ref: '#/components/schemas/timestamp' list-workload-identity-bindings-response: required: - items type: object properties: items: type: array items: $ref: '#/components/schemas/workload-identity-binding' allOf: - $ref: '#/components/schemas/paginated-response' timestamp: type: integer description: Epoch timestamp in milliseconds since January 1, 1970 UTC. format: int64 example: 1752209050377 list-service-account-api-keys-response: required: - items type: object properties: items: type: array items: $ref: '#/components/schemas/service-account-api-key' allOf: - $ref: '#/components/schemas/paginated-response' create-service-account-request: required: - name type: object properties: name: $ref: '#/components/schemas/service-account-name' email: maxLength: 255 type: string service-account-api-key: required: - public_id type: object properties: public_id: maxLength: 8 type: string description: The public, non-secret portion of the key. example: a1b2c3d4 comment: maxLength: 255 type: string created_at: $ref: '#/components/schemas/timestamp' last_used_at: $ref: '#/components/schemas/timestamp' expires_at: description: When the key expires. allOf: - $ref: '#/components/schemas/timestamp' invalid-request-problem-details: required: - errors type: object properties: errors: type: array items: $ref: '#/components/schemas/constraint-violation-error' allOf: - $ref: '#/components/schemas/problem-details' service-account-team: required: - name - uuid type: object properties: uuid: type: string format: uuid name: maxLength: 255 type: string total-count-type: type: string enum: - AT_LEAST - EXACT update-service-account-request: type: object properties: email: maxLength: 255 type: string description: The new email address. Omit this field to retain the current address, or set it to an empty string to remove the current address. suspended: type: boolean description: Whether the service account is suspended. Omit this field to retain the current state. create-workload-identity-binding-response: required: - uuid type: object properties: uuid: type: string description: The identifier of the created binding. format: uuid invalid-cel-expression-problem-details: required: - errors type: object properties: errors: type: array items: $ref: '#/components/schemas/cel-expression-error' allOf: - $ref: '#/components/schemas/problem-details' problem-details: required: - detail - title - type type: object properties: type: type: string description: A URI reference that identifies the problem type format: uri-reference default: about:blank status: maximum: 599 minimum: 400 type: integer description: HTTP status code generated by the origin server for this occurrence of the problem format: int32 example: 500 title: maxLength: 255 type: string description: Short, human-readable summary of the problem type detail: maxLength: 1024 type: string description: Human-readable explanation specific to this occurrence of the problem instance: type: string description: Reference URI that identifies the specific occurrence of the problem format: uri-reference description: An RFC 9457 problem object. externalDocs: url: https://www.rfc-editor.org/rfc/rfc9457.html x-parent: true create-service-account-api-key-response: required: - expires_at - key - public_id type: object properties: public_id: maxLength: 8 type: string example: a1b2c3d4 key: maxLength: 128 type: string description: The full, plain text key. It is returned exactly once, at creation time, and cannot be retrieved again. expires_at: description: When the key expires. allOf: - $ref: '#/components/schemas/timestamp' create-service-account-api-key-request: type: object properties: comment: maxLength: 255 type: string expires_in_days: minimum: 1 type: integer description: Number of days from now after which the key expires. Must not exceed the maximum lifetime configured with `dt.api-key.max-lifetime-days` (366 days by default). Defaults to 30 days, or the maximum lifetime if that is shorter. format: int32 cel-expression-error: required: - column - line - message type: object properties: line: type: integer description: Line number where the error occurred format: int32 column: type: integer description: Column number where the error occurred format: int32 message: type: string description: Description of the error service-account: required: - name - suspended - username type: object properties: name: $ref: '#/components/schemas/service-account-name' username: maxLength: 63 type: string description: The full username of the service account, i.e. the name with the reserved `svc:` prefix. example: svc:ci-pipeline email: maxLength: 255 type: string suspended: type: boolean description: Whether the service account is suspended. get-service-account-response: required: - permissions - teams type: object properties: teams: type: array description: The teams the service account is a member of, ordered by name. items: $ref: '#/components/schemas/service-account-team' permissions: type: array description: The permissions granted to the service account directly, ordered by name. Permissions it inherits from its teams are not included. items: maxLength: 255 type: string allOf: - $ref: '#/components/schemas/service-account' create-workload-identity-binding-request: required: - provider_name - subject type: object properties: provider_name: maxLength: 63 type: string description: The name of the workload identity provider to trust the subject of. The provider must exist. example: github-actions subject: maxLength: 512 pattern: ^[^*]+(?:[:/]\*)?$ type: string description: The `sub` claim to match. A trailing `*` makes it a prefix match, whose prefix must not be empty and must end with `:` or `/`. example: repo:acme/app:* condition: maxLength: 2048 type: string description: An optional CEL expression over the token's claims that must evaluate to `true`. The claims are available as the `claims` map, for example `claims.ref == "refs/heads/main"`. Use it when the subject alone cannot express the rule. example: claims.ref == "refs/heads/main" total-count: required: - count - type type: object properties: count: minimum: 0 type: integer description: The total number of records across all pages. Might be an exact count, or a lower bound. Refer to the `type` field for the applicable semantics. format: int64 type: $ref: '#/components/schemas/total-count-type' list-service-accounts-response: required: - items type: object properties: items: type: array items: $ref: '#/components/schemas/service-account' allOf: - $ref: '#/components/schemas/paginated-response' service-account-name: maxLength: 59 pattern: ^(?![sS][vV][cC]:)[a-zA-Z0-9][a-zA-Z0-9+=,.:@_-]*$ type: string description: The name of the service account, without the reserved `svc:` prefix. example: ci-pipeline responses: generic-error: description: Unexpected error content: application/problem+json: schema: $ref: '#/components/schemas/problem-details' invalid-request-error: description: Bad request content: application/problem+json: schema: $ref: '#/components/schemas/invalid-request-problem-details' example: type: about:blank status: 400 title: Bad Request detail: The request could not be processed because it failed validation. errors: - path: foo.bar value: baz message: Must be a number generic-forbidden-error: description: Forbidden content: application/problem+json: schema: $ref: '#/components/schemas/problem-details' example: type: about:blank status: 403 title: Forbidden detail: Not permitted to access the requested resource. generic-conflict-error: description: Forbidden content: application/problem+json: schema: $ref: '#/components/schemas/problem-details' example: type: about:blank status: 409 title: Conflict detail: The resource already exists. generic-not-found-error: description: Not found content: application/problem+json: schema: $ref: '#/components/schemas/problem-details' example: type: about:blank status: 404 title: Not Found detail: The requested resource could not be found. generic-unauthorized-error: description: Unauthorized content: application/problem+json: schema: $ref: '#/components/schemas/problem-details' example: type: about:blank status: 401 title: Unauthorized detail: Not authorized to access the requested resource. securitySchemes: apiKeyAuth: type: apiKey description: Authentication via API key. name: X-Api-Key in: header bearerAuth: type: http description: 'Authentication via opaque server-issued session token. Tokens are obtained from `POST /api/v1/user/login`, `POST /api/v1/user/oidc/login`, or `POST /api/v2/oauth/token`.' scheme: bearer bearerFormat: Opaque x-refined-from: - dependency-track-openapi-v2.yaml - dependency-track-v2-openapi.yml