---
title: "Create and track CloudPrint print jobs"
description: "Create idempotent print jobs, validate printer options and follow each job safely until it is printed or fails."
---
<nav class="docs-breadcrumb" aria-label="Breadcrumb"><a href="/docs/">CloudPrint Documentation</a><span aria-hidden="true">/</span><span>Print API</span></nav>

# Create and track CloudPrint print jobs

<p class="docs-lead">Job creation is the point where duplicate-print protection and printer compatibility matter. All options are top-level JSON fields. The response is a durable job record that must be tracked to a terminal status.</p>

## Create a job

```bash
curl -sS https://public-api.cloudprint.me/api/v1/print-jobs \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-18452-invoice-v1' \
  -d '{
    "document_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
    "printer_id": "11111111-1111-4111-8111-111111111111",
    "copies": 1,
    "intent": "invoice",
    "color_mode": "default",
    "duplex_mode": "default",
    "scale_mode": "none",
    "orientation": "default"
  }'
```

A successful request returns HTTP 201:

```json
{
  "print_job_id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
  "document_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  "document_mime_type": "application/pdf",
  "document_format": "pdf",
  "document_raw_language": null,
  "printer_id": "11111111-1111-4111-8111-111111111111",
  "status": "pending",
  "copies": 1,
  "intent": "invoice",
  "color_mode": "default",
  "duplex_mode": "default",
  "media_width_mm": null,
  "media_height_mm": null,
  "dpi": null,
  "scale_mode": "none",
  "orientation": "default",
  "offset_x_mm": 0,
  "offset_y_mm": 0,
  "margin_top_mm": 0,
  "margin_right_mm": 0,
  "margin_bottom_mm": 0,
  "margin_left_mm": 0,
  "created_at": "2026-06-08T10:12:00+00:00",
  "reserved_at": null,
  "started_at": null,
  "completed_at": null,
  "failure_reason": null
}
```

## Supported fields

| Field | Allowed values |
| --- | --- |
| `copies` | integer, minimum 1 |
| `intent` | `document`, `shipping_label`, `product_label`, `invoice`, `packing_slip`, `a4_document`, `receipt` |
| `color_mode` | `default`, `monochrome`, `color` |
| `duplex_mode` | `default`, `simplex`, `duplex_long_edge`, `duplex_short_edge` |
| `scale_mode` | `none`, `fit` |
| `orientation` | `default`, `portrait`, `landscape` |
| `offset_x_mm`, `offset_y_mm` | number from -2000 to 2000 |
| `margin_*_mm` | number from 0 to 2000 |
| `media_width_mm`, `media_height_mm` | optional number from 1 to 2000 |
| `dpi` | optional integer from 72 to 2400 |

Every non-default field must be supported by the selected printer. Invalid values return `422`; valid values that cannot be routed return `409 remote_printing.print_job.unsupported` with `details.reason`.

## Idempotency and reprints

Send `Idempotency-Key` for every create request. Repeating the same key with the same payload returns the original job; the safest retry repeats the exact serialized body. Reusing it with different input returns `409 remote_printing.print_job.idempotency_key_conflict`. A timeout retry keeps the key; an operator-approved reprint receives a new key and audit record.

## Read the result

```bash
curl -sS https://public-api.cloudprint.me/api/v1/print-jobs/bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

Terminal states are `printed`, `failed` and `cancelled`. Current non-terminal states are `pending`, `reserved` and `printing`. `printed` confirms that the operating-system spooler accepted the document; it does not confirm physical output. Treat unknown states as non-terminal. The current Public API has no result webhook, so poll the stored URL with a bounded, configurable interval and jitter; slow down on prolonged waits and obey `Retry-After`. Preserve `failure_reason` for `failed`; `cancelled` means that spool acceptance did not complete. A 2xx create response also is not proof of physical printing.

## List and reconcile jobs

```bash
curl -sS 'https://public-api.cloudprint.me/api/v1/print-jobs?limit=20' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json
{
  "print_jobs": [
    {
      "print_job_id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
      "document_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "printer_id": "11111111-1111-4111-8111-111111111111",
      "status": "printed",
      "copies": 1,
      "intent": "invoice",
      "completed_at": "2026-06-08T10:12:08+00:00",
      "failure_reason": null
    }
  ],
  "next_cursor": null
}
```

Use this endpoint to reconcile history, not as the primary lookup for a known job. Follow opaque `next_cursor` with the `cursor` query parameter until it is `null`; store `print_job_id` beside your business operation.

## Error strategy

```json
{
  "error": "remote_printing.print_job.unsupported",
  "error_code": "remote_printing.print_job.unsupported",
  "message": "The selected printer cannot route this document.",
  "details": {
    "reason": "missing_pdf_renderer"
  }
}
```

| HTTP | Meaning | Client action |
| --- | --- | --- |
| `400` | malformed OAuth, upload or JSON request | fix the request; do not retry unchanged |
| `401` | invalid credentials or expired/invalid token | refresh the API token once, then retry once |
| `403` | valid token without the required scope | change client-app grants; token refresh alone does not help |
| `404` | resource missing or belongs to another account | verify the account and stored identifier |
| `409` | idempotency conflict or unsupported print route | inspect `error_code` and `details.reason`; do not invent a new key |
| `413` | document is too large | reduce it or choose a suitable transport |
| `415` | detected/declared document type is unsupported | send a print-ready PDF or explicit supported RAW data |
| `422` | validation failed or the document did not pass security checks | change the document or request before retrying |
| `429` | rate limit exceeded | wait for `Retry-After` |
| `500` | unexpected CloudPrint failure | retry with bounded backoff and the original idempotency key |
| `503` | document security inspection is temporarily unavailable | retry with bounded backoff and the original idempotency key |

Use HTTP status for the broad class and `error`/`error_code` for branching. Use `message` only for diagnostics. Every response includes `X-Request-Id`; log it with your business ID.

## Next steps

<div class="docs-card-grid"><a class="docs-card" href="/docs/api/documents/"><strong>Upload PDF and RAW documents</strong><span>Choose multipart upload, a public HTTPS URL or Base64, and prepare PDF or RAW printer-language data for CloudPrint.</span></a>
<a class="docs-card" href="/docs/api/v1/idempotency/"><strong>Idempotent print-job creation</strong><span>Prevent duplicate physical prints when retrying CloudPrint print-job requests after a timeout or network failure.</span></a>
<a class="docs-card" href="/docs/troubleshooting/"><strong>Troubleshoot agents, printers and print jobs</strong><span>Diagnose CloudPrint integration problems by request ID, job status, agent connectivity, printer capabilities and API error code.</span></a></div>

<nav class="docs-resource-links" aria-label="Next steps"><a href="https://cloudprint.me/status/">Service status</a><a href="/docs/api/v1/explorer/">OpenAPI</a><a href="https://developer.cloudprint.me">Developer Portal</a><a href="https://my.cloudprint.me">Open account</a><a href="/docs/legal/privacy/">Privacy Policy</a><a href="/docs/legal/terms/">Terms</a><a href="/docs/legal/data-processing/">DPA</a><a href="/docs/legal/service-level-agreement/">Service Level Agreement</a></nav>