--- title: "API v2 - Conventions and shared behaviors" slug: "api-v2-conventions-and-shared-behaviors" updated: 2026-11-03T14:47:50Z published: 2026-11-03T14:47:50Z canonical: "docs.senhasegura.io/api-v2-conventions-and-shared-behaviors" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.senhasegura.io/llms.txt > Use this file to discover all available pages before exploring further. # API v2 - Conventions and shared behaviors This document describes the standard behaviors, rules, and formats that apply to all **A2A** API v2 endpoints. Read this before integrating with any v2 endpoint. --- ## Response headers Every v2 API response includes the following headers regardless of the endpoint or HTTP status code. | Header | Description | | --- | --- | | `X-Request-Id` | Unique identifier for the request, assigned by Segura™. Use this value when reporting issues to the support team. | | `ETag` | Hash representing the current state of the returned resource. Use with `If-None-Match` for conditional reads. | | `X-RateLimit-Limit` | Maximum number of requests allowed in the current time window. | | `X-RateLimit-Remaining` | Number of requests remaining in the current time window. | | `X-RateLimit-Reset` | Unix timestamp at which the current rate limit window resets. | > **Note:** When the rate limit is exceeded, the API returns `429 Too Many Requests`. Wait until `X-RateLimit-Reset` before retrying. --- ## Resource actions (`meta.actions`) Responses that return a single resource include a `meta.actions` object. Each key names an action available for that resource, and its value is the path that performs the action. This object is the intended way for an integration to discover what it can do with a resource, instead of hard-coding paths. | Field | Description | | --- | --- | | `meta.links.self` | URL of the resource itself. | | `meta.actions.<action>` | Path of an action available for the resource. The key is omitted when the action does not apply to the resource in its current state, and when the authorization does not permit it. | An absent key is not an error. The object reflects the current state of the resource, so an active resource does not offer its activation action. --- ## Conditional requests ### `If-None-Match` — conditional reads (`GET`) Use the `ETag` value from a previous response as the `If-None-Match` header in a subsequent `GET` request. If the resource hasn't changed, the server returns `304 Not Modified` with no body, saving bandwidth. ``` GET /api/v2/pam/credentials/101 If-None-Match: "abc123etag" ``` | Response | Meaning | | --- | --- | | `200 OK` | Resource has changed. Full response body is returned. | | `304 Not Modified` | Resource is unchanged. No body is returned; use the cached version. | ### `If-Match` — conditional writes (`PUT`, `PATCH`, `DELETE`) Use the `ETag` value from a previous read as the `If-Match` header in a write request. This prevents overwriting changes made by another process since your last read (optimistic concurrency control). ``` PUT /api/v2/pam/credentials/101 If-Match: "abc123etag" ``` | Response | Meaning | | --- | --- | | `2xx` | ETag matched. Write was applied. | | `412 Precondition Failed` | ETag didn't match. The resource was modified since your last read. Re-fetch before retrying. | --- ## Error format All v2 error responses use a consistent JSON structure regardless of the endpoint. ``` { "error": { "code": "api.fields.invalid", "message": "One or more requested fields do not exist in the canonical model.", "details": [ { "field": "credential.nonexistent", "reason": "Field not found in CredentialV2 schema." } ] } } ``` | Field | Type | Description | | --- | --- | --- | | `error.code` | string | Machine-readable error identifier. Use for programmatic error handling. | | `error.message` | string | Human-readable description of the error. | | `error.details` | array of objects | Additional context about the error. May be empty for generic errors. | | `error.details[].field` | string | The field or parameter that caused the error, when applicable. | | `error.details[].reason` | string | Specific reason the field or parameter was rejected. | --- ## `403` vs `404` policy The v2 API deliberately distinguishes between authorization failures and missing resources. | Code | When it's returned | | --- | --- | | `403 Forbidden` | The resource exists but the authorization doesn't have permission to access it, or the request contains a sensitive field. Segura™ returns `403` even when the caller could infer existence from the response. | | `404 Not Found` | The resource genuinely does not exist or the ID is malformed. | > **Note:** Segura™ never returns `404` to mask a `403`. If you receive `404`, the resource does not exist. If you receive `403`, the resource exists but is outside the scope of your authorization. --- ## Pagination All list endpoints support two pagination strategies. Each endpoint documents which strategies it supports. ### Offset pagination Use for standard browsing and moderate dataset sizes. | Parameter | Type | Default | Description | | --- | --- | --- | --- | | `page` | integer | `1` | Page number to retrieve. | | `limit` | integer | `50` | Number of results per page. | **Response fields:** | Field | Type | Description | | --- | --- | --- | | `meta.pagination.page` | integer | Current page number. | | `meta.pagination.limit` | integer | Results per page. | | `meta.pagination.total_items` | integer | Total matching records. May be `null` or an estimate for large datasets. | | `meta.pagination.total_pages` | integer | Total number of pages. | | `meta.pagination.count` | integer | Number of items in the current page. | | `meta.links.self` | string | URL of the current page. | | `meta.links.first` | string | URL of the first page. | | `meta.links.prev` | string | URL of the previous page. `null` on the first page. | | `meta.links.next` | string | URL of the next page. `null` on the last page. | | `meta.links.last` | string | URL of the last page. | ### Cursor-based pagination Recommended for datasets exceeding 100,000 records. More efficient than offset pagination for large volumes. | Parameter | Type | Description | | --- | --- | --- | | `cursor` | string | Opaque cursor token returned in `meta.pagination.next_cursor`. Do not decode or construct cursors manually. Cursors expire after 24 hours. | **Response fields:** | Field | Type | Description | | --- | --- | --- | | `meta.pagination.cursor` | string | Cursor representing the current position. | | `meta.pagination.next_cursor` | string | Cursor for the next page. `null` when there are no more results. | | `meta.pagination.has_more` | boolean | Indicates whether more results exist beyond the current page. | > **Warning:** `page`/`limit` and `cursor` are mutually exclusive. Sending both in the same request returns `422 Unprocessable Content`. For large datasets where `total_items` would be impractical to compute, the field may be `null` or an estimate — use `has_more` instead as your continuation signal. --- ## Field projection (`fields`) Endpoints that support `fields` return only the requested subset of the canonical model, reducing payload size. **Usage:** ``` GET /api/v2/pam/credentials/101?fields=credential.username,device.name,jit.credential_enabled ``` **Rules:** - Use dot notation to reference nested fields (e.g., `credential.username`, `device.tags`). - Request a full object by naming it without a child path (e.g., `fields=device` returns all non-sensitive `device` fields). - When `fields` is omitted, all public fields of the canonical model are returned, with `null` for fields that aren't applicable. - Fields not present in the canonical model return `422` with code `api.fields.invalid`. - Sensitive fields return `403` with code `api.fields.sensitive.not.allowed`. See [Sensitive fields](/docs/api-v2-conventions-and-shared-behaviors#sensitive-fields). - Fields outside the scope of the current authorization return `403`. **Sensitive fields — never returned:** The following fields are permanently excluded from all responses. Requesting them returns `403`: - `credential.password` - `certificate.key_file` - `certificate.key_password` - `totp.secret_key` --- ## Sorting (`sort_by`) List endpoints that support sorting accept the `sort_by` query parameter. **Usage:** ``` GET /api/v2/pam/credentials?sort_by=criticality:desc,credential.username ``` **Rules:** | Rule | Detail | | --- | --- | | Format | `field` or `field:asc` or `field:desc` | | Default direction | `asc` when no suffix is provided | | Multiple fields | Comma-separated, processed left to right | | Invalid field | Returns `422` | | Invalid direction | Returns `422` | --- ## Filters List endpoints accept filter parameters as query strings. All filter parameters are optional. ### AND and OR logic | Pattern | Logic | Example | | --- | --- | --- | | Different parameters | AND | `?device_id=123&credential.criticality=high` | | Same parameter repeated | AND (for arrays) | `?credential.tags=prod&credential.tags=finance` | | Comma-separated values | OR | `?credential.criticality=high,medium` | > **Note:** The pipe character (`|`) is not supported as an OR separator. Use comma-separated values instead. ### Boolean filter values Boolean parameters accept only `true` or `false` as string values. The values `0`, `1`, `yes`, and `no` are not accepted and return `422`. ### Validation All invalid filter parameters return an explicit error — the API never silently ignores an unrecognized filter. | Condition | Response | | --- | --- | | Non-existent field | `422 Unprocessable Content` | | Sensitive field used as filter | `422 Unprocessable Content` | | Invalid enum value | `422 Unprocessable Content` | | Invalid boolean value | `422 Unprocessable Content` | ### Examples **Exact match:** ``` GET /api/v2/pam/credentials?credential.username=svc-payments ``` **AND — multiple fields:** ``` GET /api/v2/pam/credentials?device_id=123&credential.criticality=high&jit.credential_enabled=true ``` **AND — same field (array):** ``` GET /api/v2/pam/credentials?credential.tags=prod&credential.tags=finance ``` **OR — comma-separated values:** ``` GET /api/v2/pam/credentials?credential.criticality=high,medium ``` **Multi-field sort:** ``` GET /api/v2/pam/credentials?sort_by=criticality:desc,credential.username ``` --- ## Naming conventions All v2 API endpoints follow these conventions consistently. | Convention | Rule | | --- | --- | | Path naming | `snake_case` for query parameters and response fields; `kebab-case` for compound path segments (e.g., `/group-sync`) | | Collections | Plural nouns (e.g., `/credentials`, `/devices`) | | Field names | `snake_case` in all request and response payloads. `camelCase` is not used. | | Booleans in query strings | `true` / `false` only | --- ## Authentication errors The following authentication errors apply to all v2 endpoints. | Message | Possible cause | Solution | | --- | --- | --- | | `Client authentication failed.` | Application authentication failure with the Segura™ server. | Check the authentication parameters (`Access Token URL`, `Client ID`, and `Client secret`) and request a new access token. | | `Invalid signature` | Failure in recognizing the client application URL. | Check the URL of the client application and resend the request. | | `No route matched with those values.` | Missing authorization header in the API request. | Request a new access token. | | `Request timed out.` | The request exceeded the timeout limit. | Check the connectivity between the source of the request and the Segura™ server. | --- ## Related documents - [GET | List all credentials (v2)](/v4-2/docs/api-v2-get-list-all-credentials) - [GET | List a credential by [id] (v2)](/v4-2/docs/api-v2-get-list-a-credential) - [About applications and authorizations in A2A](/v4-2/docs/a2a-about-applications-and-authorizations)