Skip to content

Migration

Move from apitemplate.io to Formfeed

Your templates are Jinja2 and your integration posts JSON. Formfeed speaks both, so a migration is an import and a base URL change, not a rewrite. The importer tells you up front what needs a look.

Free plan with 100 units a month, no credit card

1. Import the templates

Open Templates, choose Import and apitemplate.io. Enter your apitemplate.io API key and the region your integration calls, pick the templates from the list, by group or all at once, and the importer reads their HTML, CSS, settings and sample JSON. Image templates are layer designs without HTML and cannot be imported. A single template can also be pasted or dropped as exported files. The importer compiles each template, checks it against its sample data and produces a report; Create drafts then makes one Jinja2 template each, saved as a draft. On the Free plan, which holds five templates, an import stops at the limit. The CLI does the same with formfeed import apitemplate --all. Every mapping is in the migration guide.

  • Errors. Unknown filters and syntax the engine rejects, with the line.
  • Things to check. Python-only constructs, settings without an equivalent and sample keys the template reads but the data lacks.
  • What was mapped. Paper size, orientation, margins, header and footer templates, print background, scale, page ranges and the image options.

2. Compare the output

The optional compare step renders the original with your apitemplate.io key and the same data, so you can put their PDF next to the Formfeed preview before you commit. The key is used for that one call and never stored.

3. Switch the API

Publish each imported draft first: the API renders the published version. Then pick one of two routes. The compatibility endpoints for create-pdf, create-image, create-pdf-from-html and create-pdf-from-url keep apitemplate.io’s request and response shapes, so only the base URL and the key change: a Formfeed key goes into the same X-API-KEY header, and templates imported in the app keep answering to their apitemplate.io template_id. The native endpoint gives you the full API: batches, webhooks, idempotency and reproducibility.

Compatibility endpointShell
curl "https://api-eu.formfeed.dev/v1/compat/apitemplate/create-pdf?template_id=invoice-de" \
  -H "X-API-KEY: ff_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "invoice": { "number": "2026-0042", "lines": [] } }'

What is the same

  • Jinja2 syntax. qrcode and barcode are helpers of the same name (check their options), and currency_format still renders as an alias of money. There is no table filter: write such a table as HTML with a {% for %} loop (filters).
  • The settings you already use for paper, margins, headers and footers.
  • A JSON body in, a signed download URL out, valid for up to seven days and never longer than your plan keeps the file.

What is different

  • An editor with diagnostics. Autocomplete from your sample data and a paginated preview instead of a text box.
  • Templates as files. Pull and push templates with the command line, review changes in pull requests, test them in CI.
  • EU processing. Database and rendering in Frankfurt, outputs stored in the EU, with a data processing agreement.
  • EUR pricing. Plans and extra units in euros, a free plan with 100 units a month, and test keys that are not metered.

FAQ

Do template ids stay the same?
On the compatibility endpoints, yes, for templates you imported in the app with your API key: each remembers its apitemplate.io id, so template_id stays as it is. Templates imported with the command line, or pasted as files, answer to their slug or Formfeed id instead. The slug is the template’s name in lowercase with dashes (Statement of cost becomes statement-of-cost), and the native API names templates by it.
What is not covered by the compatibility endpoints?
Listing and deleting objects, listing templates, the account endpoints and the merge and watermark helpers; any other path answers 404. Their native counterparts: GET /v1/renders lists renders, DELETE /v1/renders/{id}/outputs deletes a file, GET /v1/templates lists templates, GET /v1/account and GET /v1/usage show the account, and the PDF tools merge and watermark (Starter and above).
How long does it take?
For a handful of templates, an afternoon: import, compare, publish, change the base URL. Larger sets are the same work repeated, and the command line importer reads them with your API key and region: formfeed import apitemplate --key … --source-region de --all, or --group for one group.

Start rendering today

The free plan includes 100 units a month and free test renders. Change plans when you need more.