Skip to main content
GET
/
job
/
{jobId}
Get Job Status
curl --request GET \
  --url https://api.runpulse.com/job/{jobId} \
  --header 'x-api-key: <api-key>'
{
  "job_id": "<string>",
  "status": "pending",
  "created_at": "2023-11-07T05:31:56Z",
  "updated_at": "2023-11-07T05:31:56Z",
  "result": {},
  "error": "<string>"
}

Overview

Check the status and retrieve results of an asynchronous job (e.g., submitted via /extract_async). Poll this endpoint periodically until the job reaches a terminal state (completed, failed, or canceled).

Response

The response includes job metadata and, when completed, the full extraction results.
{
  "job_id": "abc123-def456-ghi789",
  "status": "completed",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:31:45Z",
  "result": {
    "markdown": "# Document Title\n\nExtracted content...",
    "page_count": 15,
    "bounding_boxes": { ... },
    "plan-info": { ... }
  }
}

Response Fields

FieldTypeDescription
job_idstringUnique identifier for the extraction job.
statusstringCurrent job status: pending, processing, completed, failed, or canceled.
created_atstringISO 8601 timestamp when the job was submitted.
updated_atstringISO 8601 timestamp of the last status update.
resultobjectExtraction output (only present when status is completed). See Extract for result structure.
errorstringError message (only present when status is failed).

Job Status Values

StatusDescription
pendingJob is queued and waiting to be processed.
processingJob is currently being processed.
completedJob finished successfully. Results are available in the result field.
failedJob encountered an error. See error field for details.
canceledJob was canceled before completion.

Polling Strategy

We recommend polling with exponential backoff:
from pulse import Pulse
import time

client = Pulse(api_key="YOUR_API_KEY")

def poll_job(job_id: str, max_attempts: int = 60):
    """
    Poll for job completion with exponential backoff.
    
    Args:
        job_id: The job ID returned from extract_async
        max_attempts: Maximum number of polling attempts
        
    Returns:
        The extraction result when job completes
    """
    delay = 1  # Start with 1 second
    
    for attempt in range(max_attempts):
        # Get job status using the SDK
        response = client.jobs.get_job(job_id=job_id)
        
        if response.status == "completed":
            return response.result
        elif response.status == "failed":
            raise Exception(f"Job failed: {response.error}")
        elif response.status == "canceled":
            raise Exception("Job was canceled")
        
        # Still pending or processing - wait and retry
        print(f"Status: {response.status}, waiting {delay}s...")
        time.sleep(delay)
        delay = min(delay * 1.5, 10)  # Cap at 10 seconds
    
    raise Exception("Polling timeout")

# Example usage
job_id = "abc123-def456-ghi789"
result = poll_job(job_id)
print(f"Extraction complete! Content: {result.content[:100]}...")

Example Usage

Check Job Status

from pulse import Pulse

client = Pulse(api_key="YOUR_API_KEY")

# Check job status
job_id = "abc123-def456-ghi789"
response = client.jobs.get_job(job_id=job_id)

print(f"Job ID: {response.job_id}")
print(f"Status: {response.status}")
print(f"Created: {response.created_at}")

if response.status == "completed":
    print(f"Content: {response.result.content[:100]}...")
elif response.status == "failed":
    print(f"Error: {response.error}")

Complete Async Workflow

from pulse import Pulse
import time
import json

client = Pulse(api_key="YOUR_API_KEY")

# Step 1: Submit async extraction
print("Submitting async extraction...")
submit_response = client.extract_async(
    file_url="https://www.impact-bank.com/user/file/dummy_statement.pdf",
    structured_output=json.dumps({
        "schema": {
            "type": "object",
            "properties": {
                "account_holder": {"type": "string"},
                "balance": {"type": "number"}
            }
        }
    })
)

job_id = submit_response.job_id
print(f"Job submitted: {job_id}")

# Step 2: Poll for completion
delay = 1
while True:
    status_response = client.jobs.get_job(job_id=job_id)
    
    if status_response.status == "completed":
        print("Extraction complete!")
        print(f"Structured output: {status_response.result.structured_output}")
        break
    elif status_response.status in ["failed", "canceled"]:
        print(f"Job ended with status: {status_response.status}")
        break
    
    print(f"Status: {status_response.status}")
    time.sleep(delay)
    delay = min(delay * 1.5, 10)
For webhook-based notifications instead of polling, see the Webhooks documentation.

Authorizations

x-api-key
string
header
required

API key for authentication

Path Parameters

jobId
string
required

Identifier returned from an async job submission (e.g., /extract_async).

Response

Current job status payload

Current status and metadata for an asynchronous extraction job.

job_id
string
required

Identifier assigned to the asynchronous extraction job.

status
enum<string>
required

Lifecycle status for an asynchronous extraction job.

Available options:
pending,
processing,
completed,
failed,
canceled
created_at
string<date-time>
required

Timestamp when the job was accepted.

updated_at
string<date-time>

Timestamp of the last status update, if available.

result
object

Structured payload that contains extraction output when the job is completed.

error
string

Error message describing why the job failed, if applicable.