Welcome · Sign in · Create a free account

API and help

Technical reference

How it works

  1. Create a form (title, questions, template): it is saved in your library and can be downloaded as a fillable PDF.
  2. Send it to a client: they receive a link to fill it in online or download the PDF.
  3. Responses arrive in “Responses” (CSV export), by email and by webhook.

Question types: text (Short text), long (Long text), email (Email), tel (Phone), number (Number), date (Date), radio (Single choice), check (Multiple choice), select (Dropdown list), yesno (Yes / No), sign (Signature). The radio, check and select types require options (2 to 12). Templates: classique, moderne, minimal, colonnes, corporate, ardoise, juridique, elegant, encadre, lettre, immigration, sante, education, creatif, pastel, carte, cl_admin, cl_lignes, cl_tableau, cl_cases, cl_officiel, cl_compact.

REST API

Base: https://mail.formtool.app/api.php?r=… · Header Authorization: Bearer fm_… (key created in Settings) · JSON UTF-8 · 600 requests / 15 min.

CallPurpose
GET r=templatesTemplates (with SVG preview) and question types.
GET r=usagePlan, usage for the month, upgrade_url to switch to Pro.
GET/POST r=modelsLibrary of fillable PDF forms: list, or add (name, pdf_base64 — PDF with fillable fields, 15 MB max). Response 402 quota_exceeded if the plan limit is reached.
GET/POST/DELETE r=model&id=Read a template (with its fields), save its links (form_id, map : PDF field → a:<question>, x:nom, x:email, x:date, x:cabinet, x:pro) or delete it.
POST r=fillmodel_id, send_id (completed response), context optional (x:cabinet, x:pro) : returns the filled PDF (pdf_base64, or raw PDF with &raw=1). Counts toward the month’s PDF fills.
GET / POST r=formsList / create. Body: title, descr, template, questions[]. Response 402 quota_exceeded if the plan limit is reached.
GET / POST / DELETE r=form&id=Read / update (partial fields) / delete.
GET r=pdf&id= · POST r=pdfFillable PDF of a saved form, or of an on-the-fly definition (counts as a generated form). JSON response pdf_base64 ; add &raw=1 for the binary.
POST r=sendform_id, to_name, to_email, ref (your identifier), send_email (default true). Returns the fill-in link.
GET r=sends · GET r=send&id=Sends (filters form_id, ref, status=completed|sent) / one send with its responses.
GET / POST r=hooks, DELETE r=hook&id=, POST r=hook_test&id=Outgoing webhooks.
curl -X POST 'https://mail.formtool.app/api.php?r=forms' \
  -H 'Authorization: Bearer fm_…' -H 'Content-Type: application/json' \
  -d '{"title":"Initial assessment","template":"moderne","questions":[
        {"label":"Full name","type":"text","required":true},
        {"label":"Status","type":"radio","options":["Student","Worker"]}]}'

Webhooks

Event form.completed : {"id","event","created","data":{"form":{…},"send":{…},"answers":[{"label","type","value"}]}}. Headers X-Formix-Event, X-Formix-Delivery and X-Formix-Signature: t=<timestamp>,v1=<HMAC-SHA256 of "t.body" with the webhook secret>. On failure: retry after 1 min, 5 min, 30 min, 2 h, then 12 h (task cron.php).

$ok = hash_equals(hash_hmac('sha256', $t . '.' . file_get_contents('php://input'), $secret), $v1);