API de redare ZPL: ZPL în PNG și PDF prin HTTP
Un endpoint redă ZPL în PNG sau PDF. Este compatibil cu API-ul v1 al Labelary: aceleași căi, antete și erori.
Renderează o etichetă
GET https://api.openzpl.com/v1/printers/{dpmm}/labels/{width}x{height}/{index}/{zpl}
POST https://api.openzpl.com/v1/printers/{dpmm}/labels/{width}x{height}/{index}
POST https://api.openzpl.com/v1/printers/{dpmm}/labels/{width}x{height}/
dpmm | Densitate de imprimare: 6dpmm, 8dpmm, 12dpmm, 24dpmm. |
width, height | Dimensiunea etichetei în inci, de exemplu 4x6 sau 2.25x1.25. Până la 15 inci fiecare. |
index | Ce etichetă să redai, începând de la 0. Lasă-o deoparte cu ieșirea PDF pentru a obține fiecare etichetă, una pe pagină. |
zpl | Pentru GET, ZPL-ul codificat URL. Codificați # ca %23. Utilizați POST pentru orice lung. |
Cu POST, trimite ZPL-ul ca corp de solicitare brut, sau ca un câmp de formular multipart numit file.
chei API
Fără o cheie, obții 3 etichete pe zi per adresă IP, suficient pentru a încerca. Cu o cheie din tabloul tău de bord, trimite-o în antetul X-API-Key și se aplică limitele planului tău de lucru.
curl https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/0/ \ -H "X-API-Key: oz_live_…" --data-binary @label.zpl > label.png
Exemple
Fiecare trimite label.zpl, salvează label.pdf și arată mesajul de eroare al API-ului dacă ceva nu este în regulă. Pentru un PNG, solicitați image/png și adăugați indexul etichetei (/0/) la URL.
curl https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/ \
-H "Accept: application/pdf" \
--data-binary @label.zpl --fail-with-body -o label.pdf
import requests # pip install requests
with open("label.zpl", "rb") as f:
res = requests.post(
"https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/",
data=f.read(),
headers={"Accept": "application/pdf"},
timeout=30,
)
if not res.ok:
raise SystemExit(res.text)
with open("label.pdf", "wb") as f:
f.write(res.content)
// Node.js 18+; save as label.mjs
import { readFile, writeFile } from "node:fs/promises";
const res = await fetch("https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/", {
method: "POST",
headers: { Accept: "application/pdf" },
body: await readFile("label.zpl"),
});
if (!res.ok) throw new Error(await res.text());
await writeFile("label.pdf", Buffer.from(await res.arrayBuffer()));
<?php
$ch = curl_init("https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => file_get_contents("label.zpl"),
CURLOPT_HTTPHEADER => ["Accept: application/pdf"],
CURLOPT_RETURNTRANSFER => true,
]);
$pdf = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) !== 200) {
exit($pdf);
}
file_put_contents("label.pdf", $pdf);
using var http = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post,
"https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/")
{
Content = new StringContent(File.ReadAllText("label.zpl")),
};
req.Headers.Add("Accept", "application/pdf");
var res = await http.SendAsync(req);
if (!res.IsSuccessStatusCode)
throw new Exception(await res.Content.ReadAsStringAsync());
File.WriteAllBytes("label.pdf", await res.Content.ReadAsByteArrayAsync());
// Java 11+
import java.net.URI;
import java.net.http.*;
import java.nio.file.Path;
public class Label {
public static void main(String[] args) throws Exception {
var req = HttpRequest.newBuilder(
URI.create("https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/"))
.header("Accept", "application/pdf")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("label.zpl")))
.build();
var res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofByteArray());
if (res.statusCode() != 200)
throw new RuntimeException(new String(res.body()));
java.nio.file.Files.write(Path.of("label.pdf"), res.body());
}
}
package main
import (
"io"
"log"
"net/http"
"os"
)
func main() {
zpl, err := os.Open("label.zpl")
if err != nil {
log.Fatal(err)
}
req, _ := http.NewRequest("POST", "https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/", zpl)
req.Header.Set("Accept", "application/pdf")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
if res.StatusCode != 200 {
log.Fatal(string(body))
}
os.WriteFile("label.pdf", body, 0o644)
}
require "net/http"
uri = URI("https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/")
res = Net::HTTP.post(uri, File.binread("label.zpl"), "Accept" => "application/pdf")
abort res.body unless res.is_a?(Net::HTTPSuccess)
File.binwrite("label.pdf", res.body)
Invoke-WebRequest -Method Post `
-Uri "https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/" `
-Headers @{ Accept = "application/pdf" } `
-InFile "label.zpl" -OutFile "label.pdf"
Antete de cerere
| Antet | Valori | Implicit |
|---|---|---|
Accept | image/png, application/pdf | PNG |
X-Quality | Grayscale (8-biți, margini netede) sau Bitonal (1-bit, fișiere mai mici) | Grayscale |
X-Rotation | 0, 90, 180, 270, în sensul acelor de ceasornic | 0 |
X-Language | zpl, epl, tspl, auto: limbajul de tipărire al corpului. Fără acesta, un corp fără ^ sau ~ este citit ca EPL sau TSPL atunci când arată ca unul. | zpl |
X-API-Key | Cheia spațiului tău de lucru, opțională | — |
Limitări
- Without a key: 3 requests per second and 3 labels per UTC day, per IP address. With a free key from the dashboard: 20 labels per UTC day.
- Labels, not requests, count against the allowance (per UTC day on Free, per UTC calendar month on paid plans): every label rendered,
^PQcopies and PDF pages included. A 10-label PDF is 1 request and 10 labels. - Every request: up to 50 labels, a 1 MB body, 15 inches per side, and 10 seconds of render time.
- Paid plans (Pro $29/month: 10 requests/s and 100,000 labels/month, Business $99/month: 20 requests/s and 1,000,000 labels/month): subscriptions, monthly or yearly, from the dashboard's Billing page (card, through Stripe), and you can cancel at any time. The workspace's API keys move to the plan's limits as soon as the payment is approved.
- Over a limit the API answers
429withRetry-After(seconds) and a body that names the limit, e.g.ERROR: Daily limit reached: 20 labels per UTC day on this plan (^PQ copies and PDF pages count).
Răspunsuri și erori
Răspunsurile de succes conțin X-Total-Count, numărul de etichete pe care le produce ZPL, inclusiv ^PQ copii. Erorile sunt text simplu care începe cu ERROR:.
| Stare | Semnificație |
|---|---|
| 400 | Un parametru este invalid, eticheta este prea mare sau indexul este în afara intervalului. |
| 401 | Cheia API este necunoscută sau a fost revocată. |
| 406 | Antetul Accept solicită un format de ieșire care nu este disponibil încă. |
| 413 | Corpul depășește 1 MB sau ZPL produce mai mult de 50 de etichete. |
| 429 | Prea multe solicitări sau etichete pentru planul dvs. Așteptați numărul de secunde din Retry-After. |
| 503 | Eticheta a durat mai mult de 10 secunde pentru a fi generată sau serviciul este la capacitate maximă. Reîncercați sau reduceți densitatea sau dimensiunea. |
Ce deseniază motorul, ignoră sau nu suportă încă este pe the compatibility page; cât de repede se redă, măsurat pe serverul de producție, pe the benchmarks page.
Șabloane: umpleți un design salvat cu datele dvs.
Proiectați o etichetă cu {{variables}} ca locuri de rezervă, salvați-o și copiați ID-ul său din tabloul de bord: d123 pentru un design, l45 pentru o etichetă salvată. Apoi, sistemul dumneavoastră trimite doar datele, cu un cheie API.
curl https://api.openzpl.com/v1/templates/d123 \
-H "X-API-Key: oz_live_…" -H "Accept: application/pdf" \
-d '{"rows": [{"sku": "A-100"}, {"sku": "A-101"}]}' > labels.pdf
Foloseste {"data": {...}} pentru o etichetă sau {"rows": [...]} pentru până la 50. Accept oferă un PDF sau PNG, sau text/plain ZPL completat pentru a fi trimis la o imprimantă. Valorile sunt escape, astfel încât datele tale nu pot începe niciodată o comandă ZPL.
Imprimă pe o imprimantă locală
Cu print agent rulând lângă imprimantă, POST /v1/print-jobs pune ZPL în așteptare pentru aceasta, iar POST /v1/templates/{id}/print completează un design salvat. Ambele iau un nume printer și returnează un ID de lucru; GET /v1/print-jobs/{id} îți spune dacă s-a imprimat.
Întrebări
Cât costă API-ul?
Fără o cheie puteți încerca cu 3 etichete pe zi. O cheie gratuită permite 20 de etichete pe zi, iar paid plans începe de la 29 $ pe lună pentru 100.000 de etichete.
Este compatibil cu Labelary?
Da: aceleași căi, antete și erori. Schimbă numele gazdelor și trimite cheia ta, așa cum arată migration guide.
Păstrați etichetele mele?
Nu cu un API key: eticheta este redată și returnată. privacy page are detaliile și termenele.
Poate un asistent AI să-l folosească?
Da, prin intermediul MCP server: Claude, Cursor și alte asistenți pot randa etichete cu acesta.
OpenAPI și Markdown
Același contract este publicat ca OpenAPI 3.1 și ca Markdown, pentru generatoare de cod și asistenți de codare.
Ghiduri pas cu pas: Python, Node.js, PHP, C#. Migrarea de la Labelary: migration guide.