---
title: "Upload PDF and RAW documents"
description: "Choose multipart upload, a public HTTPS URL or Base64, and prepare PDF or RAW printer-language data for CloudPrint."
---
<nav class="docs-breadcrumb" aria-label="Breadcrumb"><a href="/docs/">CloudPrint Documentation</a><span aria-hidden="true">/</span><span>Print API</span></nav>

# Upload PDF and RAW documents

<p class="docs-lead">Upload data only after it is ready for the selected printer. Public API accepts PDF or a supported RAW printer language; it does not convert DOC/DOCX or buy shipping labels. Always declare RAW format and language explicitly instead of relying on content detection.</p>

## Upload a PDF

```bash
curl -sS https://public-api.cloudprint.me/api/v1/documents \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F 'file=@invoice.pdf;type=application/pdf'
```

A successful upload returns HTTP 201 and this shape:

```json
{
  "document_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  "original_filename": "invoice.pdf",
  "mime_type": "application/pdf",
  "document_format": "pdf",
  "document_raw_language": null,
  "size_bytes": 1024
}
```

Persist `document_id` for the create-job request. Before a document becomes available, CloudPrint checks it for malware, malformed or encrypted structure, active content, embedded files and unsafe page dimensions. Removable actions and interactive forms may be flattened into a safer PDF.

## Upload RAW data

```bash
curl -sS https://public-api.cloudprint.me/api/v1/documents \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F 'file=@label.txt;type=application/octet-stream' \
  -F 'document_format=raw' \
  -F 'document_raw_language=zpl'
```

The existing `documents:write` scope covers RAW uploads. Allowed RAW languages are `zpl`, `tspl`, `cpcl` and `escpos`. The selected printer must advertise the same language and RAW passthrough. CloudPrint accepts supported printing and formatting commands and rejects unknown commands, persistent writes, device configuration and file access. Do not send PDF bytes as RAW.

## Create directly from a public URL

```bash
curl -sS https://public-api.cloudprint.me/api/v1/print-jobs/from-url \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: shipment-18452-label-url-v1' \
  -d '{
    "document_url": "https://files.example.com/labels/shipment-18452.pdf",
    "document_filename": "shipment-18452.pdf",
    "printer_id": "11111111-1111-4111-8111-111111111111",
    "copies": 1,
    "intent": "shipping_label",
    "media_width_mm": 100,
    "media_height_mm": 150,
    "dpi": 203
  }'
```

The URL must use HTTPS. CloudPrint rejects localhost, private and reserved networks, embedded credentials and redirects that fail the same checks. This returns the normal print-job response.

## Create directly from Base64

```bash
curl -sS https://public-api.cloudprint.me/api/v1/print-jobs/from-base64 \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: receipt-18452-base64-v1' \
  -d '{
    "document_base64": "JVBERi0xLjQK...",
    "document_filename": "receipt-18452.pdf",
    "printer_id": "11111111-1111-4111-8111-111111111111",
    "copies": 1,
    "intent": "receipt"
  }'
```

Use this for small inline documents. Base64 increases the request size; prefer multipart or a protected short-lived public URL for larger files. This also returns the normal print-job response.

## Choose how to send the document

Multipart `/api/v1/documents` is the usual choice for files held by your backend. Use `/from-url` when the final file already has a safe public HTTPS URL, and `/from-base64` for small generated documents. Send an `Idempotency-Key` with every method that creates a job.

## Validate before upload

Confirm content type, file size, page or media dimensions and orientation. Convert office formats to PDF yourself. For a carrier label, first obtain the final PDF or ZPL from the carrier or shipping platform; CloudPrint starts at printing. Server-side inspection is a final safety boundary, not a replacement for validating generated documents.

## Handle upload errors

`400` means a malformed multipart request, `413` means too large, `415` means the detected or declared type is unsupported, and `422` means the request is invalid or the document failed security checks. Do not retry an unchanged `422` request. A `503` means inspection is temporarily unavailable; retry it with bounded backoff and the same idempotency key. Branch on `error`, inspect `error_code` for a more specific reason, use `message` only for operator diagnostics, and store `X-Request-Id`.

## Next steps

<div class="docs-card-grid"><a class="docs-card" href="/docs/api/agents-and-printers/"><strong>Local Printer API for web and SaaS applications</strong><span>Connect a web or SaaS backend to local printers through CloudPrint Agent, discover printer queues via API and route jobs by stable printer ID.</span></a>
<a class="docs-card" href="/docs/api/print-jobs/"><strong>Create and track CloudPrint print jobs</strong><span>Create idempotent print jobs, validate printer options and follow each job safely until it is printed or fails.</span></a>
<a class="docs-card" href="/docs/guides/shipping-labels/"><strong>Label Printing API for shipping and warehouse workflows</strong><span>Send carrier-generated PDF or RAW labels in ZPL, TSPL or CPCL from ecommerce, WMS or ERP software to the correct local printer and track the final status.</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>