Sari la conținut

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}/
dpmmDensitate de imprimare: 6dpmm, 8dpmm, 12dpmm, 24dpmm.
width, heightDimensiunea etichetei în inci, de exemplu 4x6 sau 2.25x1.25. Până la 15 inci fiecare.
indexCe etichetă să redai, începând de la 0. Lasă-o deoparte cu ieșirea PDF pentru a obține fiecare etichetă, una pe pagină.
zplPentru 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

AntetValoriImplicit
Acceptimage/png, application/pdfPNG
X-QualityGrayscale (8-biți, margini netede) sau Bitonal (1-bit, fișiere mai mici)Grayscale
X-Rotation0, 90, 180, 270, în sensul acelor de ceasornic0
X-Languagezpl, 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-KeyCheia 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, ^PQ copies 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 429 with Retry-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:.

StareSemnificație
400Un parametru este invalid, eticheta este prea mare sau indexul este în afara intervalului.
401Cheia API este necunoscută sau a fost revocată.
406Antetul Accept solicită un format de ieșire care nu este disponibil încă.
413Corpul depășește 1 MB sau ZPL produce mai mult de 50 de etichete.
429Prea multe solicitări sau etichete pentru planul dvs. Așteptați numărul de secunde din Retry-After.
503Eticheta 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.

Feedback