Пропусни до съдържанието

ZPL рендеринг API: ZPL в PNG и PDF през HTTP

Един крайна точка рендерира ZPL в PNG или PDF. Тя е съвместима с v1 API на Labelary: същите пътища, заглавия и грешки.

Рендерирайте етикет

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Плътност на печата: 6dpmm, 8dpmm, 12dpmm, 24dpmm.
width, heightРазмер на етикет в инчове, например 4x6 или 2.25x1.25. До 15 инча всеки.
indexКой етикет да се обработи, започвайки от 0. Оставете го, ако изходът е PDF, за да получите всеки етикет, един на страница.
zplЗа GET, URL-кодирането на ZPL. Кодирайте # като %23. Използвайте POST за всичко дълго.

С POST, изпратете ZPL като сурово съдържание на заявката или като многочастично поле с име file.

API ключове

Без ключ получавате 3 етикета на ден на IP адрес, достатъчно, за да го опитате. С ключ от таблото за управление, изпратете го в заглавката X-API-Key и ограниченията на плана на вашето работно пространство важат.

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

Примери

Всеки изпраща label.zpl, запазва label.pdf и показва съобщението за грешка на API, ако нещо е сбъркано. За PNG, поискайте image/png и добавете индекса на етикета (/0/) към 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"

Заглавия на заявката

ЗаглавиеСтойностиПо подразбиране
Acceptimage/png, application/pdfPNG
X-QualityGrayscale (8-бит, гладки ръбове) или Bitonal (1-бит, по-малки файлове)Grayscale
X-Rotation0, 90, 180, 270, по посока на часовниковата стрелка0
X-Languagezpl, epl, tspl, auto: езикът на принтера на тялото. Без него, тяло без ^ или ~ се чете като EPL или TSPL, когато изглежда така.zpl
X-API-KeyКлюч за вашето работно пространство, по избор—

Ограничения

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

Отговори и грешки

Успешните отговори съдържат X-Total-Count, броя на етикетите, които ZPL произвежда, включително ^PQ копия. Грешките са обикновен текст, който започва с ERROR:.

СтатусЗначение
400Параметърът е невалиден, етикетът е прекалено голям или индексът е извън диапазона.
401API ключът е неизвестен или е отменен.
406Accept заглавието иска формат на изхода, който все още не е наличен.
413Тялото е над 1 MB, или ZPL произвежда повече от 50 етикети.
429Твърде много заявки или етикети за вашия план. Изчакайте броя секунди в Retry-After.
503Етикетът отне повече от 10 секунди за рендериране, или услугата има капацитет. Опитайте отново или намалете плътността или размера.

Какво рисува двигателят, игнорира или все още не поддържа, можете да намерите на the compatibility page; колко бързо се рендерира, измерено на продукционния сървър, на the benchmarks page.

Шаблони: попълнете запазен дизайн с вашите данни

Проектирайте етикет с {{variables}} плейсхолдъри, запазете го и копирайте ID-то му от таблото: d123 за проект, l45 за запазен етикет. След това вашата система изпраща само данните с 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

Използвайте {"data": {...}} за един етикет или {"rows": [...]} за до 50. Accept дава PDF или PNG, или text/plain запълнения ZPL за изпращане на принтер. Стойностите са ескейпнати, така че данните ви никога не могат да стартират ZPL команда.

Отпечатайте на локален принтер

С print agent, работещ до принтера, POST /v1/print-jobs поставя ZPL в опашка за него и POST /v1/templates/{id}/print попълва запазен дизайн. И двата изискват име на printer и връщат ID на задачата; GET /v1/print-jobs/{id} ви казва дали е отпечатано.

Въпроси

Колко струва API?

Без ключ можете да го тествате с 3 етикета на ден. Безплатен ключ позволява 20 етикета на ден, а paid plans започват от $29 на месец за 100,000 етикета.

Съвместимо ли е с Labelary?

Да: същите пътеки, заглавки и грешки. Променете името на хоста и изпратете вашия ключ, както показва migration guide.

Запазвате ли моите етикети?

Не с API ключ: етикетът е генериран и върнат. privacy page има подробности и крайни срокове.

Може ли AI асистент да го използва?

Да, чрез MCP server: Claude, Cursor и други асистенти могат да рендерират етикети с него.

OpenAPI и Markdown

Същият договор е публикуван като OpenAPI 3.1 и Markdown, за генератори на код и помощници по кодиране.

Стъпка по стъпка ръководства: Python, Node.js, PHP, C#. Преминаване от Labelary: migration guide.

Обратна връзка