Description
Track, cancel, and retry an asynchronous rotation in PAM Core. When you request a rotation, Segura® accepts it, returns 202 Accepted with a job, and runs the rotation in the background. The job resource reports what happened to that rotation.
Two endpoints create rotation jobs:
- POST | Rotate credential rotates a credential's password.
- POST | Rotate SSH key rotates an SSH key.
This document covers reading a job and the two actions you can take on it:
| Operation | Endpoint |
|---|---|
| Read a job | GET /api/v2/pam/jobs/{job-id} |
| Cancel a queued rotation | POST /api/v2/pam/jobs/{job-id}/cancel |
| Retry a failed rotation | POST /api/v2/pam/jobs/{job-id}/retry |
A job records the rotation currently in flight and its outcome. It is not a history of past rotations. Segura® exposes rotation history through the per-credential audit trail, which is documented separately.
Prerequisites
- Authorization with read and write permission to PAM Core granted by the administrator in A2A. For more information, access How to manage authorizations in A2A.
- A valid OAuth 2.0 access token. For more information, access How to authenticate an application in A2A.
- A job created by a rotation request. You get the job identification code from the
202 Acceptedresponse of the rotation, indata.job.idand in theLocationresponse header.
Read a job
GET /api/v2/pam/jobs/{job-id}
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
job-id |
integer | Yes | Unique identification code of the job. Segura® assigns it when it accepts the rotation. |
Example request
GET {{url}}/api/v2/pam/jobs/45
Response
HTTP/1.1 200 OK
A rotation that completed:
{
"data": {
"job": {
"id": "45",
"type": "rotate",
"state": "succeeded",
"retry_count": 1,
"created_at": "2026-08-20T18:37:52-03:00",
"started_at": "2026-08-20T15:37:54-03:00",
"finished_at": "2026-08-20T15:39:11-03:00",
"related_resource": {
"type": "credential",
"id": "102"
}
}
}
}
A rotation that failed carries the reason in error:
{
"data": {
"job": {
"id": "51",
"type": "rotate",
"state": "failed",
"retry_count": 1,
"created_at": "2026-08-20T19:58:06-03:00",
"started_at": "2026-08-20T16:58:11-03:00",
"finished_at": "2026-08-20T16:58:24-03:00",
"related_resource": {
"type": "credential",
"id": "1"
},
"error": {
"code": "pam.rotation.execution_failed",
"message": "Credential does not have a template configured for this operation."
}
}
}
}
Response body fields
| Field | Type | Description |
|---|---|---|
data |
object | Response envelope. |
data.job |
object | The rotation job. See the following table. |
job
| Field | Type | Description |
|---|---|---|
→id |
string | Unique identification code of the job. |
→type |
string | Job type. rotate for a rotation. |
→state |
string | Current state of the job. Allowed values: queued, running, succeeded, failed, canceled. See Job states. |
→retry_count |
integer | Number of attempts recorded for this job. |
→created_at |
string | Date and time the job was created, in ISO 8601 format. See Known issues. |
→started_at |
string | Date and time the rotation started running, in ISO 8601 format. Empty while the job is queued, and for a job canceled before it started. |
→finished_at |
string | Date and time the rotation stopped running, in ISO 8601 format. Set for succeeded and failed jobs. Empty for canceled jobs, and while a job is queued or running. |
→related_resource |
object | The resource the rotation acts on. |
→→type |
string | Type of the source resource. credential for a credential rotation. See Known issues for the SSH key path. |
→→id |
string | Unique identification code of the source resource. |
→error |
object | Present only when state is failed. |
→→code |
string | Machine-readable failure code. Example: pam.rotation.execution_failed. |
→→message |
string | Description of the failure. Examples: Credential does not have a template configured for this operation., Automatic change disabled. |
Job states
| State | Terminal | Description |
|---|---|---|
queued |
No | The rotation was accepted and is waiting to start. You can cancel the job while it is in this state. |
running |
No | The password or key change is in progress on the target device. |
succeeded |
Yes | The change was applied on the device and stored in the vault. |
failed |
Yes | The rotation ran and did not complete. The error object carries the reason. |
canceled |
Yes | The rotation was canceled before it started. No change was attempted. |
A rotation has no documented timeout. If the target device is unreachable, the job can stay running for a long time, and the source resource stays locked to further rotations while it does. Do not write a polling loop that assumes a terminal state arrives within a fixed window.
Cancel a queued rotation
POST /api/v2/pam/jobs/{job-id}/cancel
Cancels a rotation that has not started yet. The job moves to canceled and no change is attempted on the device.
HTTP/1.1 200 OK
{
"data": {
"job": {
"id": "48",
"type": "rotate",
"state": "canceled",
"retry_count": 0,
"created_at": "2026-08-20T19:57:13-03:00",
"started_at": null,
"finished_at": null,
"related_resource": {
"type": "credential",
"id": "102"
}
}
}
}
You can cancel a rotation only while its job is queued. Once the job is running, the change is already under way on the device and cannot be called back.
Retry a failed rotation
POST /api/v2/pam/jobs/{job-id}/retry
Requests a new attempt for a rotation that ended in failed.
Only a failed job can be retried. Any other state returns 409 with the code api.job.invalid_transition:
{
"error": {
"code": "api.job.invalid_transition",
"message": "Only a failed rotation can be retried.",
"details": {
"state": "running"
}
}
}
Errors
| HTTP code | Message | Possible cause | Solution |
|---|---|---|---|
401 |
api.auth.token.invalid |
The access token is missing or has expired. | Request a new access token. |
404 |
api.resource.not_found |
The job doesn't exist, or it's outside the scope of the authorization. | Check the identification code sent in the path. |
409 |
api.job.invalid_transition |
The action isn't valid for the job's current state, for example retrying a job that isn't failed. |
Read the job and check its state before sending the action. |
429 |
rate_limit_exceeded |
The request rate limit was exceeded. | Reduce the request rate and try again. |
500 |
api.internal.error |
Internal server error. | Contact the Segura® support team. |
A job outside the scope of your authorization returns 404, the same status as a job that doesn't exist. You can't tell the two apart, which is deliberate.
Known issues
These affect the job resource in this release.
| Field | Behavior | Tracked as |
|---|---|---|
created_at |
On a credential rotation job, the value is the UTC time carrying a -03:00 offset, so it resolves three hours ahead of the real creation time and can appear later than started_at. The SSH key path is correct. |
SSGR-11972 |
related_resource.type |
A job created by an SSH key rotation reports credential instead of a type identifying an SSH key. The id is correct. Resolving type plus id can therefore lead to the wrong resource, because a credential and an SSH key can share an identification code. |
SSGR-11909 |
finished_at |
Empty on a canceled job even though the job is in a terminal state. |
SSGR-11997 |
Use started_at and finished_at for timing, and treat created_at as unreliable for ordering.
For authentication error messages and the shared error format, access API v2 - Conventions and shared behaviors.