Check job status by UUID

Retrieves the current status of an asynchronous job by providing the job UUID and payload hash. This endpoint is used to poll for job completion status after submitting a case file creation request. The endpoint is rate-limited to 20 requests per minute per submission. No authentication is required as the UUID and payload hash provide the necessary security.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…

Open API 3.0 Specs

The Open API 3.0 Specs are available on the following urls:

Table of Contents


Overview

When you create a case file using the simple case file creation API, the operation is processed asynchronously. The API immediately returns a job UUID and payload hash. You must use these two values to poll this status endpoint and, once the job has completed, retrieve the case file ID. The case file ID is what you use to track the case file afterwards (for example, its signing progress), so store the case file ID as soon as the job completes.

Key Features:

  • No authentication required (UUID + payload hash provide security)
  • Rate limited to 20 requests per minute per submission
  • Real-time job status tracking
  • Detailed result information, including the case file ID, when completed
  • Job status records are retained for 14 days after creation

Authentication

No authentication required for this endpoint. Security is provided through:

  • The unique job UUID
  • The payload hash

Both values are returned in the response from the simple case file creation endpoint. These two values together ensure only authorized users can check job status.


Data Retention

Job status records — the uuid, payloadHash, payload, and result (which contains the case file ID) — are retained for 14 days after the job is created. After 14 days the record is permanently deleted and the status endpoint returns 404 Not Found.

This retention applies only to the job status record, not to the case file itself. The case file continues to exist in Penneo after the job record expires; you simply track it from then on using its case file ID. So make sure you retrieve and store the case file ID within the 14-day window.


Request Structure

Request Body

The request body must be a JSON object with two required fields.

Required Properties

PropertyTypeFormatDescriptionExample
uuidstringUUID v4The unique identifier of the job to check"123e4567-e89b-12d3-a456-426614174000"
payloadHashstringSHA-256 hashThe hash of the original payload used for verification"3a7bd3e2360a3d485f2a5f4d8e6f1e8b9c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f"

Request Example

{
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "payloadHash": "3a7bd3e2360a3d485f2a5f4d8e6f1e8b9c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f"
}

Getting UUID and PayloadHash

When you create a case file, with the simple case file creation API, the values are returned in the response:

{
  "message": "Job created",
  "status": "handled",
  "jobs": [
    {
      "uuid": "123e4567-e89b-12d3-a456-426614174000",
      "payloadHash": "3a7bd3e2360a3d485f2a5f4d8e6f1e8b9c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f",
      ...
    }
  ]
}

💡 Tip: Store both the uuid and payloadHash immediately after creating a job so you can check its status later.


Response Structure

Success Response (200 OK)

When the job is found, you receive a complete job object with all details.

Response Properties

PropertyTypeFormatRequiredDescription
uuidstringUUIDYesUnique identifier for the job
jobStatusstringenumYesCurrent status of the job. See Job Status Values
payloadobjectJSONYesThe original payload submitted with the job
payloadHashstringSHA-256YesSHA-256 hash of the payload
resultobject | nullJSONYesThe result of job execution (populated when jobStatus is "completed")
createdAtstringISO 8601YesDate and time when the job was created
updatedAtstringISO 8601YesDate and time when the job was last updated
errorMessagestring | null-YesError message if job failed (only present when jobStatus is "failed")

Automatic Retry of Failed Jobs

📘

In our response, we return the retries and maxRetries properties, which are defaulted to 0. Currently, automatic retry of failed jobs is not enabled as it is part of our experimental features. We will update this information once the mechanism is available and the documentation is complete.

Success Response Example

{
  "uuid": "7e47477c-e543-43ad-90a9-50e6abe9abdc",
  "type": "etl-queue",
  "payloadHash": "1d3644ac95ec37b073d9d8be2dca5da66f36533397a88c0462dcc219d049db70",
  "jobStatus": "completed",
  "errorMessage": null,
  "retries": 0,
  "maxRetries": 0,
  "createdAt": "2025-11-11T10:34:46.140Z",
  "updatedAt": "2025-11-11T10:34:51.574Z",
  "result": {
    "data": {
      "caseFile": {
        "id": 1234
      },
      "signingLinks": [
        {
          "name": "John Doe",
          "role": "signer",
          "signerId": 12345,
          "signOrder": [
            0
          ],
          "signingLink": "https://app.penneo.com/signing/12345-ABCDE-56789-FGHIJ-KLMNO-PQRS"
        }
      ]
    },
    "errors": null,
    "success": true
  }
}

Error Response (404 Not Found)

When the job is not found or the UUID and payloadHash doesn't match.

Error Properties

PropertyTypeDescriptionExample
statusCodenumberHTTP status code404
messagestringHuman-readable error message"Job not found"

Error Response Example

{
  "statusCode": 404,
  "message": "Job not found"
}

Common reasons for 404:

  • Job UUID doesn't exist
  • PayloadHash doesn't match the job
  • Job has expired (see Data Retention)
  • Job has been deleted

Job Status Values

The jobStatus field indicates the current state of the job.

StatusDescriptionNext Action
pendingJob is waiting to be processedContinue polling
processingJob is currently being executedContinue polling
completedJob finished successfullyCheck result field for outcome
failedJob execution failedCheck errorMessage field for details

Status Workflow

┌─────────┐
│ pending │ → Job created, waiting in queue
└────┬────┘
     ↓
┌────────────┐
│ processing │ → Job is being executed
└─────┬──────┘
      ↓
   ┌──┴──────────────────────────┐
   │                             │
   ↓                             ↓
┌──────────┐                  ┌────────┐
│completed │ → get CF defails │ failed │ → Check errorMessage
└──────────┘                  └────────┘

Examples

Checking Job Status (Completed)

Request:

const url = 'https://sandbox.penneo.com/send/api/v1/queue/public/status';

const data = {
  uuid: '123e4567-e89b-12d3-a456-426614174000',
  payloadHash: '3a7bd3e2360a3d485f2a5f4d8e6f1e8b9c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f'
};

async function checkQueueStatus() {
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });

    const responseBody = await response.text();

    if (!response.ok) {
      console.error('Error status:', response.status);
      console.error('Error body:', responseBody);
      return;
    }

    // If response is JSON, parse it
    const result = JSON.parse(responseBody);
    console.log('Queue Status:', result);

  } catch (error) {
    console.error('Fetch failed:', error.message);
  }
}

checkQueueStatus();

Response:

{
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "type": "etl-queue",
  "payloadHash": "3a7bd3e2360a3d485f2a5f4d8e6f1e8b9c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f",
  "jobStatus": "completed",
  "errorMessage": null,
  "retries": 0,
  "maxRetries": 5,
  "createdAt": "2025-11-14T12:12:38.413Z",
  "updatedAt": "2025-11-14T12:12:41.957Z",
  "result": {
    "data": {
      "caseFile": {
        "id": 1234
      },
      "signingLinks": [
        {
          "name": "Test User",
          "role": "Signer",
          "signerId": 2044563,
          "signOrder": [
            0
          ],
          "signingLink": "https://sandbox.penneo.com/signing/ABCDE-12345-FGHIJ-KLMNO-56789-PQRST"
        }
      ]
    },
    "errors": null,
    "success": true
  }
}

Error Handling

HTTP Status Codes

Status CodeDescriptionAction
200 OKJob found and status returnedProcess the job status
404 Not FoundJob not found or hash mismatchVerify UUID and payload hash
429 Too Many RequestsRate limit exceeded (>20 req/min)Wait before retrying
500 Internal Server ErrorServer errorRetry after a delay

Usage Guide

Polling Strategy

Implement a polling strategy to check job status without overwhelming the API.

Recommended Polling Intervals

Job StatusPolling IntervalMax Duration
pending5 seconds10 minutes, but we expect much faster
processing3-5 seconds5 minutes, but we expect much faster
completedStop polling-
failedStop polling-

Best Practices

1. Store Job Details Immediately

After creating a case file, immediately store the uuid and payloadHash — they are returned only once and cannot be
retrieved later. Use them to poll for status and to obtain the case file ID once the job completes; the case file ID
is what you use to track the case file afterwards. Job status records are retained for 14 days after creation, so
retrieve and persist the case file ID within that window.

2. Set Reasonable Timeouts and respect the Rate Limits

Don't poll indefinitely. Set a reasonable timeout:

  • Recommended timeout: at least 10 minutes until you see a status change but usually you will have the CaseFile
    created or failed in a few seconds depending on the number of signers and documents.
  • Maximum attempts: 20 polls / minute / CaseFile. After exhausting the limit, 429 HTTP responses will be returned.
  • Polling interval: recommend minimum 3 seconds to fit the maximum attempts but we count the number of attempts per minute, so it is at your discretion if you want to exponentially increased the interval to fit the 20 requests / minute.

Security Considerations

Protect Credentials

The uuid and payloadHash together provide access to job status:

  • Store them securely
  • Don't share payload hashes/uuid publicly

Integration Workflow

Complete Case File Creation + Status Check Flow

1. Create Case File
   ↓
2. Receive Job UUID + Payload Hash
   ↓
3. Store UUID + Hash in Database/Your own storage
   ↓
4. Start Polling (every 3-5 seconds)
   ↓
5. Check Job Status
   ↓
   ├─→ pending/processing → Continue Polling
   ├─→ completed → Process Result
   └─→ failed → Handle Error
flowchart TD
    A[Start: createAndMonitorCaseFile] --> B[Step 1: Create Case File]
    B --> C{Is createResponse.status 'handled'?}
    C -- No --> D[Throw Error: Failed to create case file]
    C -- Yes --> E[Step 2: Store job details in database]
    E --> F[Step 3 Poll job status call public/status every 3s]
    
    %% Polling loop
    F --> G{completedJob.jobStatus}
    G -- pending/processing --> H[Wait 3 seconds then poll again]
    H --> F

    G -- completed --> I[Update job as 'completed' in database]
    I --> J[Return completedJob.result]

    G -- failed --> K[Update job as 'failed' in database]
    K --> L[Return failedJob.result]

Body Params

Job identification information including UUID and payload hash for verification.

Request body for checking job status. Both UUID and payloadHash are required for security verification.

uuid
required

The UUID of the job to check. This is returned when the job is created.

string
required

The SHA-256 hash of the payload. This is returned when the job is created and is used to verify the request authenticity.

Responses

Language
URL
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json