API

Jobs

Every API call to cloudlayer.io creates a job. Jobs track the status, parameters, processing time, and cost of each generation request. Use the Jobs API to monitor async requests, debug failed generations, and audit API usage.

Endpoints

GET /v1/jobs/:id
GET /v1/jobs
GET /v2/jobs/:id
GET /v2/jobs

Get a Single Job

Retrieve a specific job by its ID.

GET /v1/jobs/:id
GET /v2/jobs/:id

Path Parameters

ParameterTypeRequiredDescription
idstringYesThe unique job ID.

Examples

cURL

curl -X GET "https://api.cloudlayer.io/v2/jobs/job_abc123def456" \
  -H "X-API-Key: your-api-key-here"

JavaScript (fetch)

const jobId = "job_abc123def456";

const response = await fetch(
  `https://api.cloudlayer.io/v2/jobs/${jobId}`,
  {
    headers: {
      "X-API-Key": "your-api-key-here",
    },
  }
);

const job = await response.json();
console.log(job);

Python (requests)

import requests

job_id = "job_abc123def456"

response = requests.get(
    f"https://api.cloudlayer.io/v2/jobs/{job_id}",
    headers={"X-API-Key": "your-api-key-here"},
)

job = response.json()
print(job)

Response

{
  "id": "job_abc123def456",
  "uid": "usr_xyz789",
  "apiKeyUsed": "key_...last4",
  "type": "html/pdf",
  "status": "completed",
  "params": {
    "format": "letter",
    "margin": {
      "top": "1in",
      "bottom": "1in"
    },
    "printBackground": true
  },
  "size": 245760,
  "processTime": 2340,
  "apiCreditCost": 1,
  "worker": "worker-us-east-1a",
  "timestamp": "2024-01-15T10:30:00.000Z"
}

List Jobs

Retrieve a paginated list of all jobs, ordered by creation date (newest first).

GET /v1/jobs
GET /v2/jobs

Query Parameters

ParameterTypeDefaultDescription
limitnumber25Number of jobs to return (max 100).
offsetnumber0Number of jobs to skip for pagination.

Examples

cURL

# Get the 25 most recent jobs
curl -X GET "https://api.cloudlayer.io/v2/jobs" \
  -H "X-API-Key: your-api-key-here"

# Paginate: get jobs 11-20
curl -X GET "https://api.cloudlayer.io/v2/jobs?limit=10&offset=10" \
  -H "X-API-Key: your-api-key-here"

JavaScript (fetch)

const response = await fetch(
  "https://api.cloudlayer.io/v2/jobs?limit=10",
  {
    headers: {
      "X-API-Key": "your-api-key-here",
    },
  }
);

const jobs = await response.json();

for (const job of jobs) {
  console.log(`${job.id} | ${job.type} | ${job.status} | ${job.processTime}ms`);
}

Python (requests)

import requests

response = requests.get(
    "https://api.cloudlayer.io/v2/jobs",
    params={"limit": 10},
    headers={"X-API-Key": "your-api-key-here"},
)

jobs = response.json()
for job in jobs:
    print(f"{job['id']} | {job['type']} | {job['status']} | {job['processTime']}ms")

Response

[
  {
    "id": "job_abc123def456",
    "uid": "usr_xyz789",
    "apiKeyUsed": "key_...last4",
    "type": "html/pdf",
    "status": "completed",
    "params": {
      "format": "letter",
      "printBackground": true
    },
    "size": 245760,
    "processTime": 2340,
    "apiCreditCost": 1,
    "worker": "worker-us-east-1a",
    "timestamp": "2024-01-15T10:30:00.000Z"
  },
  {
    "id": "job_ghi789jkl012",
    "uid": "usr_xyz789",
    "apiKeyUsed": "key_...last4",
    "type": "url/image",
    "status": "completed",
    "params": {
      "url": "https://example.com",
      "imageType": "png"
    },
    "size": 102400,
    "processTime": 3150,
    "apiCreditCost": 1,
    "worker": "worker-us-east-1b",
    "timestamp": "2024-01-15T10:25:00.000Z"
  }
]

Response Fields

FieldTypeDescription
idstringUnique job identifier (e.g., "job_abc123def456").
uidstringThe user ID that owns this job.
apiKeyUsedstringA masked version of the API key used to create this job (last 4 characters visible). Useful for auditing which key was used in multi-key setups.
typestringThe job type, matching the API endpoint used. See Job Types below.
statusstringCurrent job status. See Job Statuses below.
paramsobjectThe parameters that were sent with the API request (excluding the html or template body for privacy). Useful for debugging and understanding what configuration produced a given result.
sizenumberSize of the generated output file in bytes. 0 for pending or failed jobs.
processTimenumberTime in milliseconds from when the job started processing to completion. 0 for pending jobs.
apiCreditCostnumberNumber of API credits consumed by this job.
workerstringIdentifier of the worker instance that processed this job. Useful for support and debugging.
timestampstringISO 8601 timestamp of when the job was created.

Job Types

TypeDescription
html/pdfHTML to PDF generation
url/pdfURL to PDF generation
template/pdfTemplate to PDF generation
html/imageHTML to image generation
url/imageURL to image generation
template/imageTemplate to image generation

Job Statuses

StatusDescription
pendingThe job has been created and is waiting to be picked up by a worker.
processingThe job is currently being processed by a worker.
completedThe job finished successfully. The generated asset is available for download.
failedThe job failed. Check the response for error details.

Polling for Async Jobs

When using async mode, poll the job endpoint to check when processing is complete:

JavaScript (fetch)

async function waitForJob(jobId, apiKey, maxWaitMs = 60000) {
  const startTime = Date.now();
  const pollInterval = 1000; // 1 second

  while (Date.now() - startTime < maxWaitMs) {
    const response = await fetch(
      `https://api.cloudlayer.io/v2/jobs/${jobId}`,
      { headers: { "X-API-Key": apiKey } }
    );

    const job = await response.json();

    if (job.status === "completed") {
      return job;
    }

    if (job.status === "failed") {
      throw new Error(`Job ${jobId} failed`);
    }

    // Wait before polling again
    await new Promise((resolve) => setTimeout(resolve, pollInterval));
  }

  throw new Error(`Job ${jobId} timed out after ${maxWaitMs}ms`);
}

// Usage
const job = await waitForJob("job_abc123def456", "your-api-key-here");
console.log(`Completed in ${job.processTime}ms, size: ${job.size} bytes`);

Python (requests)

import time
import requests


def wait_for_job(job_id, api_key, max_wait_seconds=60):
    start_time = time.time()
    poll_interval = 1  # seconds

    while time.time() - start_time < max_wait_seconds:
        response = requests.get(
            f"https://api.cloudlayer.io/v2/jobs/{job_id}",
            headers={"X-API-Key": api_key},
        )
        job = response.json()

        if job["status"] == "completed":
            return job

        if job["status"] == "failed":
            raise Exception(f"Job {job_id} failed")

        time.sleep(poll_interval)

    raise TimeoutError(f"Job {job_id} timed out after {max_wait_seconds}s")


# Usage
job = wait_for_job("job_abc123def456", "your-api-key-here")
print(f"Completed in {job['processTime']}ms, size: {job['size']} bytes")

Usage Analytics

Use the Jobs API to build your own usage dashboards and analytics:

import requests

response = requests.get(
    "https://api.cloudlayer.io/v2/jobs",
    params={"limit": 100},
    headers={"X-API-Key": "your-api-key-here"},
)

jobs = response.json()

# Compute statistics
total_credits = sum(job["apiCreditCost"] for job in jobs)
avg_process_time = sum(job["processTime"] for job in jobs) / len(jobs)
total_bytes = sum(job["size"] for job in jobs)
failed_count = sum(1 for job in jobs if job["status"] == "failed")

print(f"Total credits used: {total_credits}")
print(f"Average processing time: {avg_process_time:.0f}ms")
print(f"Total output size: {total_bytes / 1048576:.2f} MB")
print(f"Failed jobs: {failed_count}")

Tips

  • Debugging failures: When a job fails, check the params field to see what configuration was used. Common issues include timeouts (increase the timeout parameter), unreachable URLs, and malformed HTML.
  • API key auditing: The apiKeyUsed field shows which API key was used for each job. Use this to audit usage across multiple keys or team members.
  • Process time optimization: Monitor processTime across jobs to identify slow generation patterns. Consider reducing viewport size, using waitUntil: "domcontentloaded", or simplifying your HTML content.
  • Pagination: The list endpoint returns a maximum of 100 items per request. Use limit and offset to page through your complete job history.