Salta al contingut

API de renderitzat ZPL: ZPL a PNG i PDF a través d'HTTP

Un punt final renderitza ZPL a PNG o PDF. És compatible amb l'API v1 de Labelary: mateixes rutes, encapçalaments i errors.

Renderitza una etiqueta

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}/
dpmmDensitat d'impressió: 6dpmm, 8dpmm, 12dpmm, 24dpmm.
width, heightMida etiqueta en polzades, per exemple 4x6 o 2.25x1.25. Fins a 15 polzades cadascun.
indexQuina etiqueta renderitzar, començant des de 0. Deixa-ho sense especificar amb sortida PDF per obtenir cada etiqueta, una per pàgina.
zplPer GET, el ZPL codificat en URL. Codifiqueu # com %23. Utilitzeu POST per a qualsevol cosa llarga.

Amb POST, envia el ZPL com el cos de la sol·licitud en brut, o com un camp de formulari multipart anomenat file.

Claus de l'API

Sense una clau, obteniu 3 etiquetes al dia per adreça IP, suficient per provar-ho. Amb una clau del vostre tauler de control, envieu-la en el capçalera X-API-Key i s'apliquen els límits del pla del vostre espai de treball.

curl https://api.openzpl.com/v1/printers/8dpmm/labels/4x6/0/ \
  -H "X-API-Key: oz_live_…" --data-binary @label.zpl > label.png

Exemples

Cada un envia label.zpl, guarda label.pdf i mostra el missatge d'error de l'API si alguna cosa va malament. Per un PNG, demaneu image/png i afegiu l'índex de l'etiqueta (/0/) a 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"

Capçaleres de la sol·licitud

CapçaleraValorsPer defecte
Acceptimage/png, application/pdfPNG
X-QualityGrayscale (8-bits, vores suaus) o Bitonal (1-bit, fitxers més petits)Grayscale
X-Rotation0, 90, 180, 270, en el sentit de les agulles del rellotge0
X-Languagezpl, epl, tspl, auto: el llenguatge de la impressora del cos. Sense això, un cos sense ^ o ~ es llegeix com a EPL o TSPL quan s'assembla a un.zpl
X-API-KeyLa teva clau d'espai de treball, opcional—

Límits

  • 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).

Respostes i errors

Les respostes aconseguides porten X-Total-Count, el nombre d'etiquetes que produeix el ZPL, amb ^PQ còpies incloses. Els errors són text simple que comença amb ERROR:.

EstatSignificat
400Un paràmetre és invàlid, l'etiqueta és massa gran, o l'índex està fora de rang.
401La clau de l'API és desconeguda o ha estat revocada.
406La capçalera Accept sol·licita un format de sortida que encara no està disponible.
413El cos supera 1 MB, o el ZPL produeix més de 50 etiquetes.
429Masses sol·licituds o etiquetes per al teu pla. Espera el nombre de segons indicat a Retry-After.
503L'etiqueta ha tardat més de 10 segons a renderitzar, o el servei està a capacitat. Torna a intentar-ho, o redueix la densitat o la mida.

El que dibuixa, ignora o encara no suporta el motor està en the compatibility page; quina velocitat té de renderitzar, mesurada al servidor de producció, en the benchmarks page.

Plantilles: ompliu un disseny desat amb les vostres dades

Dissenyeu una etiqueta amb marcadors de {{variables}}, deseu-la, i copieu el seu ID del vostre tauler: d123 per a un disseny, l45 per a una etiqueta desada. Després el vostre sistema envia només les dades, amb una clau 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

Utilitzeu {"data": {...}} per a una etiqueta o {"rows": [...]} per a un màxim de 50. Accept proporciona un PDF o PNG, o text/plain el ZPL omplert per enviar a una impressora. Els valors estan escapats, així que les vostres dades mai poden començar un comandament ZPL.

Imprimiu en una impressora local

Amb el print agent funcionant al costat de la impressora, POST /v1/print-jobs posa en espera ZPL per a ella i POST /v1/templates/{id}/print omple un disseny desat. Ambdues requereixen un nom de printer i retornen un ID de feina; GET /v1/print-jobs/{id} et diu si s'ha imprès.

Preguntes

Quant costa l'API?

Sense una clau pots provar-ho amb 3 etiquetes al dia. Una clau gratuïta permet 20 etiquetes al dia, i paid plans comencen a $29 al mes per 100,000 etiquetes.

És compatible amb Labelary?

Sí: els mateixos camins, capçaleres i errors. Canvieu el nom d'àncora i envieu la vostra clau, tal com mostra el migration guide.

Feu servir les meves etiquetes?

No amb una clau API: l'etiqueta es renderitza i s'envia de nou. La privacy page té els detalls i els terminis.

Pot un assistent d'IA utilitzar-ho?

Sí, a través del MCP server: Claude, Cursor i altres assistents poden generar etiquetes amb això.

OpenAPI i Markdown

El mateix contracte es publica com OpenAPI 3.1 i com Markdown, per a generadors de codi i assistents de codificació.

Guies pas a pas: Python, Node.js, PHP, C#. Migrant des de Labelary: migration guide.

Comentaris