API رندر ZPL: ZPL به PNG و PDF از طریق HTTP
یک نقطه انتهایی ZPL را به PNG یا PDF رندر میکند. این با 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. حداکثر ۱۵ اینچ برای هر کدام. |
index | کدام برچسب را رندر کنیم، شروع از ۰. با خروجی PDF این را خالی بگذارید تا هر برچسب را یک صفحه دریافت کنید. |
zpl | برای GET، ZPL URL-encoded را وارد کنید. # را به صورت %23 کدگذاری کنید. برای هر چیز طولانی از POST استفاده کنید. |
با POST، ZPL را به عنوان بدنه درخواست خام ارسال کنید، یا به عنوان یک فیلد فرم چندگانه به نام file.
کلیدهای API
بدون کلید، شما روزانه ۳ برچسب به ازای هر آدرس 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"
هدرهای درخواست
| سرصفحه | مقدارها | پیشفرض |
|---|---|---|
Accept | image/png, application/pdf | PNG |
X-Quality | Grayscale (8 بیت، لبههای نرم) یا Bitonal (1 بیت، فایلهای کوچکتر) | Grayscale |
X-Rotation | 0, 90, 180, 270، به سمت عقربههای ساعت | 0 |
X-Language | zpl, 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,
^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).
پاسخها و خطاها
پاسخهای موفق شامل X-Total-Count، تعداد برچسبهایی که ZPL تولید میکند، به همراه ^PQ نسخه هستند. خطاها متن سادهای هستند که با ERROR: شروع میشوند.
| وضعیت | معنی |
|---|---|
| 400 | یک پارامتر نامعتبر است، برچسب خیلی بزرگ است یا ایندکس خارج از محدوده است. |
| 401 | کلید API ناشناس است یا لغو شده است. |
| 406 | هدر Accept درخواست فرمت خروجی میکند که هنوز در دسترس نیست. |
| 413 | بدنه بیش از 1 مگابایت است یا ZPL بیش از 50 لیبل تولید میکند. |
| 429 | درخواستها یا لیبلهای بیش از حد برای طرح شما. به تعداد ثانیههای موجود در Retry-After منتظر باشید. |
| 503 | لیبل بیش از 10 ثانیه برای رندر زمان برد، یا سرویس به ظرفیت خود رسیده است. دوباره تلاش کنید یا چگالی یا اندازه را کاهش دهید. |
آنچه که موتور رسم میکند، نادیده میگیرد یا هنوز پشتیبانی نمیکند در the compatibility page است؛ سرعت رندر آن، که در سرور تولید اندازهگیری میشود، در the benchmarks page.
قالبها: پر کردن یک طراحی ذخیرهشده با دادههای شما
یک برچسب با جایگزینهای {{variables}} طراحی کنید، آن را ذخیره کنید و شناسه آن را از داشبورد خود کپی کنید: 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 پر شده را برای ارسال به چاپگر. مقادیر.escape شدهاند، بنابراین دادههای شما هرگز نمیتوانند یک فرمان ZPL را آغاز کنند.
چاپ روی چاپگر محلی
با print agent در حال اجرا در کنار پرینتر، POST /v1/print-jobs ZPL را برای آن در صف قرار میدهد و POST /v1/templates/{id}/print یک طراحی ذخیره شده را پر میکند. هر دو نام printer را میپذیرند و یک شناسه شغل را برمیگردانند؛ GET /v1/print-jobs/{id} به شما میگوید آیا چاپ شده است یا نه.
سوالات
هزینه API چقدر است؟
بدون کلید میتوانید با 3 برچسب در روز امتحان کنید. یک کلید رایگان اجازه میدهد 20 برچسب در روز، و paid plans از 29 دلار در ماه برای 100,000 برچسب شروع میشود.
آیا با Labelary سازگار است؟
بله: همان مسیرها، هدرها و خطاها. نام میزبان را تغییر دهید و کلید خود را ارسال کنید، همانگونه که migration guide نشان میدهد.
آیا برچسبهای من را نگه میدارید؟
بدون کلید API: برچسب رندر میشود و برگشت داده میشود. privacy page جزئیات و زمانبندیها را دارد.
آیا یک دستیار هوش مصنوعی میتواند از آن استفاده کند؟
بله، از طریق MCP server: Claude، Cursor و سایر دستیاران میتوانند برچسبها را با آن رندر کنند.
OpenAPI و Markdown
همان قرارداد به عنوان OpenAPI 3.1 و به عنوان Markdown منتشر شده است، برای تولیدکنندگان کد و دستیاران کدنویسی.
راهنماهای مرحله به مرحله: Python، Node.js، PHP، C#. مهاجرت از Labelary: migration guide.