İçeriğe geç
getnextpdf.com

kararlılık: Beta

Bir faturayı REST üzerinden uçtan uca işleyin

Tek bir faturayı JSON’dan, NextPDF Connect Temsili Durum Aktarımı (REST) yüzeyi üzerinden, her seferinde tek bir ağ alışverişiyle yerel olarak doğrulanmış bir PDF’ye dönüştürün. Bu tarif, POST /api/v1/jobs uç noktasına bir işleme işi gönderir, yinelemeye karşı güvenli yolu göstermek için gönderimi aynı Idempotency-Key altında yeniden oynatır, GET /api/v1/jobs/{id} uç noktasını yoklar, PDF’yi GET /api/v1/jobs/{id}/result üzerinden indirir, baytları qpdf --check ile denetler ve tamamlanan işi siler.

Aşağıdaki her yanıt, gerçek bir core katmanı Connect dağıtımından (RoadRunner altında nextpdf/server, http://localhost:8080 adresine bağlı) birebir alınmış bir yakalamadır. Tek değiştirilen şey, $NEXTPDF_CONNECT_TOKEN ortam değişkeni olarak gösterilen API anahtarıdır; iş tanımlayıcıları, istek tanımlayıcıları, zaman damgaları, üst bilgiler ve gövde baytları tam olarak sunucunun döndürdüğü değerlerdir. Date ve X-Request-Id gibi üst bilgi değerleri elbette sizin dağıtımınızda farklı olacaktır.

Bu tarif, her alışverişi tam olarak okuyabilmeniz için tek bir belge üzerinden ilerler. Çok sayıda belge, sınırlı eşzamanlılık ve Retry-After odaklı yoklama döngüleri için, aynı iş yüzeyini kullanan İlerleme takibiyle PDF’leri toplu üretin sayfasına bakın.

Sunucu tarafı, standart Connect dağıtımıdır:

Terminal window
composer require nextpdf/server

Bu tarifin istemci tarafı curl ve qpdf’ten oluşur; bu nedenle onu herhangi bir HTTP istemcisine taşıyabilirsiniz. Önce dağıtımınızın değerlerini dışa aktarın:

/docs/connect/quickstart/
export NEXTPDF_CONNECT_URL="http://localhost:8080"
export NEXTPDF_CONNECT_TOKEN="npk_live_{kid}_{secret}" # your real key
# Key provisioning and server startup live in the quickstart:

Zaman uyumsuz iş yüzeyi, gönderimi almadan ayırır: bir işleme isteği gönderirsiniz, bir iş kaydı alırsınız ve iş completed durumuna ulaştığında sonucu getirirsiniz. İşleme isteğinin kendisi, sıralı bir operations dizisidir — her aktarımda Connect araç çağrılarını destekleyen aynı işlem türleri (set_font, add_text, add_table, add_image, add_page) ve belge düzeyindeki alanlar (page_size, orientation, title, author).

Birazdan okuyacağınız dökümü iki sözleşme ayrıntısı şekillendirir:

  • Idempotent gönderim. Idempotency-Key ile anahtarlanan bir gönderim, ilk seferinde 201 Created, yeniden oynatıldığında ise aynı iş kaydıyla 200 OK döndürür; böylece bir ağ yeniden denemesi asla iki kez işlemez.
  • Gönderim zaten uç durumda olabilir. Geçerli sürüm, işi POST yanıtını vermeden önce satır içi olarak işler; bu nedenle gönderim yanıtı zaten status: "completed" taşıyabilir — aşağıda olduğu gibi. Uç duruma kadar yoklama sözleşmesi, kararlı API yapısıdır: yoklama döngüsünü yazın ve ilki de dahil olmak üzere herhangi bir denemede bir uç durumu kabul edin.

Herhangi bir şey göndermeden önce dağıtımınızın neyi sunduğunu doğrulayabilirsiniz: GET /api/v1/capabilities, API anahtarınızın katmanının erişebileceği işlem kataloğunu döndürür. Burada yakalanan core katmanı dağıtımında yalnızca core işlemleri listelenmiştir; resmi katalog her zaman çalışan sunucunun kendi yanıtıdır, bu sayfa değil.

AlışverişYöntem ve yolYakalanan durum
İşleme işini gönderinPOST /api/v1/jobs201 Created
Aynı gönderimi yeniden oynatınPOST /api/v1/jobs (aynı Idempotency-Key)200 OK
İş kaydını yoklayınGET /api/v1/jobs/{id}200 OK
PDF’yi indirinGET /api/v1/jobs/{id}/result200 OK, application/pdf
Tamamlanan işi silinDELETE /api/v1/jobs/{id}204 No Content

Kimlik doğrulama, her /api/v1/* isteğinde bir taşıyıcı belirteçtir: Authorization: Bearer npk_live_{kid}_{secret}. Başarılı JSON yanıtları { "data": ..., "meta": ... } zarfını paylaşır; üzerinde işlem yaptığınız alanlar data altında bulunur.

İşleme isteğini invoice.json dosyasına yazın. Bu, düz ve belirlenimci bir işlem listesidir — kalın bir başlık satırı, bir düzenleme satırı ve bir satır kalemi tablosu:

{
"page_size": "A4",
"orientation": "portrait",
"title": "Invoice INV-2026-0042",
"author": "Aurora Fixtures Ltd.",
"operations": [
{ "type": "set_font", "family": "helvetica", "style": "B", "size": 16 },
{ "type": "add_text", "text": "Invoice INV-2026-0042" },
{ "type": "set_font", "family": "helvetica", "style": "", "size": 10 },
{ "type": "add_text", "text": "Issued 2026-07-08 by Aurora Fixtures Ltd. Payment is due within 30 days.", "width": 0, "line_height": 5 },
{ "type": "add_table", "html": "<table><tr><th>Item</th><th>Qty</th><th>Unit price</th><th>Amount</th></tr><tr><td>Cable tray, 300 mm</td><td>12</td><td>18.40</td><td>220.80</td></tr><tr><td>Mounting kit</td><td>4</td><td>9.75</td><td>39.00</td></tr><tr><td>Site delivery</td><td>1</td><td>25.00</td><td>25.00</td></tr><tr><td>Total (EUR)</td><td></td><td></td><td>284.80</td></tr></table>" }
]
}

Buradaki fatura alanları örnek verilerdir. Her işlem için yetkili argüman şeması, dağıtımınızın bildirdiği şemadır — MCP üzerinden tools/list, bu isteğin kullandığı her işlem türü için tam giriş şemasını döndürür.

Terminal window
curl -sS -i -X POST "$NEXTPDF_CONNECT_URL/api/v1/jobs" \
-H "Authorization: Bearer $NEXTPDF_CONNECT_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: inv-2026-0042" \
--data-binary @invoice.json

Sunucu 201 Created yanıtı verir:

HTTP/1.1 201 Created
Cache-Control: no-store
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'
Content-Type: application/json; charset=utf-8
Referrer-Policy: no-referrer
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: NextPDF Connect
X-Ratelimit-Remaining: 99
X-Request-Id: 019f3fd6-c6ed-727c-958e-2fa4370ba97e
Date: Wed, 08 Jul 2026 03:47:48 GMT
Transfer-Encoding: chunked
{
"data": {
"job_id": "job_9bd0808960f10eb568484acc",
"status": "completed",
"created_at": "2026-07-08T03:47:48+00:00",
"started_at": "2026-07-08T03:47:48+00:00",
"completed_at": "2026-07-08T03:47:48+00:00",
"result_url": "/api/v1/jobs/job_9bd0808960f10eb568484acc/result"
},
"meta": {
"request_id": "019f3fd6-c6ed-727c-958e-2fa4370ba97e",
"timestamp": "2026-07-08T03:47:48+00:00",
"duration_ms": 63.31,
"api_version": "v1"
}
}

İş, bu yakalamada zaten uç durumdadır — status, "completed" değerinde ve result_url mevcut — çünkü geçerli sürüm, yanıt vermeden önce satır içi olarak işler. Buna bel bağlamayın: gönderim yanıtını ilk yoklama sonucu olarak ele alın ve diğer her yoklama gibi data.status üzerinden dallanın.

Tam olarak aynı komutu yeniden çalıştırın — aynı Idempotency-Key, aynı gövde:

Terminal window
curl -sS -i -X POST "$NEXTPDF_CONNECT_URL/api/v1/jobs" \
-H "Authorization: Bearer $NEXTPDF_CONNECT_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: inv-2026-0042" \
--data-binary @invoice.json

Sunucu, aynı job_id ile 200 OK201 değil — döndürür ve ikinci bir işleme gerçekleşmez (meta.duration_ms değerini ilk yanıtla karşılaştırın):

HTTP/1.1 200 OK
Cache-Control: no-store
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'
Content-Type: application/json; charset=utf-8
Referrer-Policy: no-referrer
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: NextPDF Connect
X-Ratelimit-Remaining: 99
X-Request-Id: 019f3fd6-c756-7226-bc85-b255d75bd449
Date: Wed, 08 Jul 2026 03:47:48 GMT
Transfer-Encoding: chunked
{
"data": {
"job_id": "job_9bd0808960f10eb568484acc",
"status": "completed",
"created_at": "2026-07-08T03:47:48+00:00",
"started_at": "2026-07-08T03:47:48+00:00",
"completed_at": "2026-07-08T03:47:48+00:00",
"result_url": "/api/v1/jobs/job_9bd0808960f10eb568484acc/result"
},
"meta": {
"request_id": "019f3fd6-c756-7226-bc85-b255d75bd449",
"timestamp": "2026-07-08T03:47:48+00:00",
"duration_ms": 1.03,
"api_version": "v1"
}
}
Terminal window
curl -sS -i "$NEXTPDF_CONNECT_URL/api/v1/jobs/job_9bd0808960f10eb568484acc" \
-H "Authorization: Bearer $NEXTPDF_CONNECT_TOKEN"
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'
Content-Type: application/json; charset=utf-8
Referrer-Policy: no-referrer
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: NextPDF Connect
X-Ratelimit-Remaining: 98
X-Request-Id: 019f3fd7-0038-7131-b71e-4c69e637233b
Date: Wed, 08 Jul 2026 03:48:02 GMT
Transfer-Encoding: chunked
{
"data": {
"job_id": "job_9bd0808960f10eb568484acc",
"status": "completed",
"created_at": "2026-07-08T03:47:48+00:00",
"started_at": "2026-07-08T03:47:48+00:00",
"completed_at": "2026-07-08T03:47:48+00:00",
"result_url": "/api/v1/jobs/job_9bd0808960f10eb568484acc/result"
},
"meta": {
"request_id": "019f3fd7-0038-7131-b71e-4c69e637233b",
"timestamp": "2026-07-08T03:48:02+00:00",
"duration_ms": 0.24,
"api_version": "v1"
}
}

Bu yoklama uç bir kaydı gösterir; bu nedenle Retry-After üst bilgisi ve poll_url alanı yoktur. Bir iş hâlâ pending veya running durumundayken, sunucu her yoklamada Retry-After (2 saniyelik bir aralık) ayarlar — sıkı bir döngüde yoklamak yerine buna uyun.

Terminal window
curl -sS -D result-headers.txt \
"$NEXTPDF_CONNECT_URL/api/v1/jobs/job_9bd0808960f10eb568484acc/result" \
-H "Authorization: Bearer $NEXTPDF_CONNECT_TOKEN" \
-o invoice-inv-2026-0042.pdf
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Disposition: attachment; filename="job-job_9bd0808960f10eb568484acc.pdf"
Content-Length: 3663
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'
Content-Type: application/pdf
Referrer-Policy: no-referrer
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: NextPDF Connect
X-Ratelimit-Remaining: 98
X-Request-Id: 019f3fd7-0056-711e-acad-9f7ac5f21ba7
Date: Wed, 08 Jul 2026 03:48:02 GMT

Gövde, PDF ikili verisidir — bu yakalamada 3.663 bayt, Content-Length üst bilgisiyle eşleşir — ve burada atlanmıştır. invoice-inv-2026-0042.pdf dosyasına yazılır.

Content-Type: application/pdf içeren bir 200, tek başına gövdenin iyi biçimli bir PDF olduğunun kanıtı değildir. qpdf ile bir yapısal denetim çalıştırın:

Terminal window
qpdf --check invoice-inv-2026-0042.pdf

Yukarıda indirilen dosya için yakalanan çıktı:

checking invoice-inv-2026-0042.pdf
PDF Version: 2.0
File is not encrypted
File is not linearized
No syntax or stream encoding errors found; the file may still contain
errors that qpdf cannot detect

qpdf’nin kendi ifadesi dürüst sınırı çizer: bu, bir sözdizimi ve akış denetimidir, herhangi bir standarda göre bir uygunluk belirlemesi değildir.

Terminal window
curl -sS -i -X DELETE "$NEXTPDF_CONNECT_URL/api/v1/jobs/job_9bd0808960f10eb568484acc" \
-H "Authorization: Bearer $NEXTPDF_CONNECT_TOKEN"
HTTP/1.1 204 No Content
Cache-Control: no-store
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'
Content-Type: application/json; charset=utf-8
Referrer-Policy: no-referrer
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: NextPDF Connect
X-Ratelimit-Remaining: 97
X-Request-Id: 019f3fd7-0084-722f-bf54-3dabead8aeea
Date: Wed, 08 Jul 2026 03:48:02 GMT

Silme işleminden sonra iş kaydı ve depolanan sonucu kaybolur; işe yönelik sonraki bir GET isteği 404 döndürür.

  • Yalnızca HTTP durumuna göre değil, data.status üzerinden dallanın. Gönderim, yeniden oynatma ve yoklamanın tümü bir iş kaydıyla 2xx döndürür; yaşam döngüsü durumu data.status alanında bulunur (pending, running, completed, failed, cancelled).
  • Farklı bir gövdeyle yeniden oynatılan bir anahtar, 409 Conflict verir. Idempotent 200 yeniden oynatma yalnızca gövde, özgün gönderimle eşleştiğinde gerçekleşir. Bir anahtarı asla farklı içerik için yeniden kullanmayın.
  • Tamamlanmadan önce /result isteği 409 verir. Yalnızca bir yoklama completed gösterdikten sonra indirin. 409, incelemeniz gereken normal bir yanıttır, bir aktarım hatası değil — her Connect tarifinin izlediği aynı aktarım-durum ayrımı (bkz. Tarif kuralları).
  • İşler sahibiyle sınırlıdır. Bir API anahtarı altında gönderilen bir iş, başka bir anahtara görünmez: sahipler arası bir GET, 403 değil 404 döndürür. Gönderdiğiniz kimlik bilgisiyle yoklayın.
  • progress bulunmayabilir. Yakalanan kayıt hiçbir progress alanı taşımaz, çünkü iş zaten uç durumdaydı. Sunucu, uç durumda olmayan bir iş için ilerlemeyi izlediğinde, data.progress, 0 ile 100 arasında bir tam sayıdır; eksik bir alanı sıfır değil, bilinmeyen olarak değerlendirin.
  • failed bir iş, data.error taşır. Onu kaydedin; körü körüne yeniden göndermeyin.

Bir işleme işi, bir gönderim, en fazla birkaç yoklama ve bir indirmeye mal olur. Yakalanan meta.duration_ms değerleri durumu özetler: gönderimde faturayı işlemek için 63,31 ms, hiç iş yapmayan idempotent yeniden oynatma için 1,03 ms ve milisaniyenin altında durum okumaları. Sıkı bir döngü yerine sunucunun Retry-After temposuyla yoklayın; durum okuması ucuzdur ama bedava değildir ve hız sınırlayıcı bunu bütçeler (yakalanan üst bilgilerde X-Ratelimit-Remaining değerinin azalışını izleyin). Toplu işlemler için, her şeyi aynı anda göndermek yerine, devam eden işleri sınırlayın — toplu tarif bu döngüyü uygular.

  • Taşıyıcı belirteci yalnızca Authorization üst bilgisinde tutun. Asla bir sorgu dizesinde, bir günlük satırında veya işlenmiş (commit edilmiş) bir dosyada değil. Yukarıdaki döküm, tam da bu nedenle bir ortam değişkeni kullanır.
  • İndirilen baytlara güvenmeden önce doğrulayın. 5. adım akışın bir parçasıdır, isteğe bağlı bir ek değil: onu arşivlemeden veya iletmeden önce yanıtın bir PDF olduğunu denetleyin (en azından %PDF üst bilgisi, yapı için qpdf --check).
  • Artık ihtiyaç duymadığınız tamamlanmış işleri silin. 6. adım, depolanan sonucu sunucudan kaldırır; aksi takdirde tamamlanmış bir iş, sunucunun iş çöp toplaması onu kaldırana kadar indirilebilir kalır.
  • En az ayrıcalıklı bir anahtar kullanın. Bu akış, bir core katmanı işleme anahtarına ihtiyaç duyar, fazlasına değil.

Bu tarif, normatif bir standart iddiası ortaya koymaz. Connect zaman uyumsuz iş REST uç noktalarını çalıştırır ve sunucunun tanımladığı iş kaydı alanlarını okur. qpdf --check adımı yalnızca yapısal bütünlüğü doğrular — “the file may still contain errors that qpdf cannot detect”, qpdf’nin kendi uyarısıdır ve yukarıda birebir alıntılanmıştır. Bir standarda (PDF/A-4, PDF/UA) uygunluğu belirlemek bağımsız bir doğrulayıcının işidir ve farklı bir yüzeydir — bu sınır için bkz. Adlandırılmış standart denetimi çalıştırın.