API docs

Base URL: https://api.slipkiln.com. All requests and responses are JSON, except render endpoints, which return application/pdf.

Quickstart

  1. Get a free API key (50 documents/month).
  2. Save it in your shell: export SLIPKILN_KEY=sk_…
  3. Send HTML or JSON and get a PDF back.
curl -X POST https://api.slipkiln.com/v1/render/template \
  -H "Authorization: Bearer $SLIPKILN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template":"invoice","data":{"number":"INV-1001","currency":"USD",
       "customer":{"name":"Acme Co."},
       "items":[{"description":"Consulting","qty":10,"unit_price":120}]}}' \
  -o invoice.pdf

Authentication

Send your key as a bearer token: Authorization: Bearer sk_…. Keys are shown once at signup and stored only as a hash, so we can't recover a lost key. Email support@slipkiln.com if you lose yours. Keep keys server-side. Don't ship them in browser or mobile code.

Create a key with POST /v1/signup {"email":"you@company.com"} → 201 {"api_key":"sk_…","plan":"free","monthly_limit":50}. One account per email.

POST/v1/render/html

Render your own HTML/CSS with a headless Chromium.

FieldType
htmlstring, requiredFull HTML document or fragment (≤ 2 MB). Images, fonts and CSS must be inlined as data: URIs. External URLs are blocked.
optionsobjectSee render options.
curl -X POST https://api.slipkiln.com/v1/render/html \
  -H "Authorization: Bearer $SLIPKILN_KEY" -H "Content-Type: application/json" \
  -d '{"html":"<h1 style=\"color:#0f766e\">Hello PDF</h1>","options":{"format":"Letter","margin":{"top":"20mm"}}}' \
  -o hello.pdf

Successful responses include x-usage-month: documents rendered by your account this month.

POST/v1/render/template

{"template": "invoice" | "receipt" | "certificate", "data": {…}, "options": {…}}. All text is HTML-escaped. GET /v1/templates (no auth) returns every template with full example data.

Templates

Shared brand object (all templates):

brand.namestringShown when no logo is given
brand.logostringBase64 data:image/png|jpeg|gif|webp|svg+xml;base64,… only
brand.colorstringHex accent color, e.g. #0f766e
brand.email, brand.websitestringContact lines
brand.addressstring[]Address lines

invoice (A4)

numberstringInvoice number
issue_date, due_datestringPrinted as given
currencystringISO 4217, default USD
customerobjectname, email, address (string[])
itemsarray{description, qty, unit_price}, max 500. Totals are computed.
tax_ratenumberPercent, e.g. 8.25
notesstringFooter note

receipt (A5)

number, datestring
payment_methodstringe.g. "Visa •••• 4242"
currency, tax_rate, itemsSame as invoice
customer.namestring

certificate (A4 landscape)

titlestringe.g. "Certificate of Completion"
recipientstringName
descriptionstringBody text
datestring
signerobjectname, title
certificate_idstringPrinted bottom-right

Render options

formatA4 | A5 | Letter | Legal
landscapeboolean
margin{top,right,bottom,left}, values like 10mm, 0.5in, 20px
print_backgroundboolean, default true
javascriptboolean, default false (HTML endpoint only; network stays blocked)

Account & billing

GET /v1/mePlan and usage this month
POST /v1/billing/checkout {"plan":"starter|growth|scale"}Returns {url} to Stripe Checkout
POST /v1/billing/change-plan {"plan":…}Switch paid plans (prorated)
POST /v1/billing/portalReturns {url} to the Stripe billing portal (card, invoices, cancel)

Or use the Billing page.

Errors

Errors are JSON: {"error":"code","message":"…"}.

StatuserrorMeaning
400invalid_request, invalid_template, invalid_email, invalid_planBad input
401unauthorizedMissing/invalid key
402quota_exceededFree plan's 50 docs used this month
408render_timeoutRender took over 15 s
409email_exists, already_subscribedConflict
413render_too_large / body too largeRequest > 2 MB or PDF > 20 MB
422render_failedChromium could not render
429Rate limited; retry after the retry-after header
503render_busyTemporarily at capacity; retry with backoff

Limits & security

  • 60 requests/minute per key; signup 5/hour per IP.
  • Free: 50 successful documents per calendar month (UTC). Failed renders don't count. Paid plans: included documents, then per-document overage (see pricing).
  • Request body ≤ 2 MB; PDF ≤ 20 MB; 15 s per render.
  • Rendering runs in an isolated Chromium with no network access: only data: URIs load. JavaScript is off unless you set options.javascript.
  • Documents are processed in memory and not stored after delivery.