Parse documents inside Zapier

ParseForMe connects to Zapier through Webhooks by Zapier. A Custom Request action posts a file — or the URL of one — to the ParseForMe API, and a Catch Hook trigger receives the extracted fields as soon as parsing finishes. There is no template to draw and no parsing rules to maintain.

Drop a document to try it — freeNo signup to start. Get 30 free tokens when you sign in.

Is there a ParseForMe app in the Zapier directory?

Not yet. ParseForMe connects through Webhooks by Zapier, Zapier’s own HTTP module — the route most APIs take before a listed app exists. It works in every Zap, in both directions, and needs no waiting list; check your Zapier plan includes the Webhooks app before you build.

How a file reaches ParseForMe

Zapier hands the next step a link to the file rather than its bytes, so the action posts JSON with a sourceUrl and ParseForMe fetches it over https. PDF, DOCX, PNG, JPEG, TIFF and WebP up to 20 MB are accepted, and the document type is detected when you do not say which it is.

How the parsed fields come back

Parsing is asynchronous, so results arrive by webhook: register a Zapier Catch Hook URL and every parsed document fires it, extracted fields included. A scheduled Zap reading the documents list, filtered by when documents were created, is the backstop for anything a delivery misses.

What this integration is not

There is no listed app, so there are no dynamic field dropdowns: you map the JSON fields yourself, once, using the field list the API returns. Parsing spends tokens per page exactly as it does in the dashboard, and a Zap can spend them faster than a person can.

How to set it up

  1. Create an API key

    Nothing else works without one. Keys are created in the ParseForMe dashboard — under Settings → API keys, or from the inline form on any in-app integration guide. The key is shown once, starts with pfm_live_ and is 52 characters long; store it in your automation platform’s credential store, never in a step’s visible fields. Owners and admins can create keys, a workspace can hold up to 10 active keys, and revoking one takes effect immediately. Send it as a bearer token and check it with /v1/me before you build anything else.

    curl -s https://api.parseforme.com/v1/me \
      -H "Authorization: Bearer pfm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    
    # {"workspaceId":"…","workspaceName":"Acme","keyName":"Zapier","balance":420}
  2. Add a “Webhooks by Zapier → Custom Request” action

    Zapier hands the next step a URL for a file, not the bytes, so use the JSON form of POST /v1/documents: method POST, URL https://api.parseforme.com/v1/documents, data pass-through off, and a JSON body whose sourceUrl is mapped to the file field from your trigger. ParseForMe fetches that https URL itself. Add kind only when you already know the document type — left out, the type is detected. You get a 202 back with the document and its id.

    POST https://api.parseforme.com/v1/documents
    
    Headers
      Authorization: Bearer pfm_live_…
      Content-Type: application/json
    
    Data
      {
        "sourceUrl": "{{1__attachment_url}}",
        "filename": "{{1__attachment_name}}",
        "kind": "invoice"
      }
  3. Stop a replayed Zap parsing the same file twice

    Zaps get replayed — by an autoreplay, by a hand-run, by a trigger that fires twice. Send an Idempotency-Key header holding something stable from the trigger (the message id, the row id) and a repeat call returns the SAME document instead of spending tokens again. The header accepts up to 128 characters of letters, digits and _ - : . characters.

    POST /v1/documents
    Host: api.parseforme.com
    Authorization: Bearer pfm_live_…
    Idempotency-Key: gmail-{{1__message_id}}
    Content-Type: application/json
    
    {"sourceUrl": "https://…/invoice-1042.pdf"}
  4. Trigger a Zap when a document is parsed

    Parsing is asynchronous, so the fields arrive by webhook. Create a Zap starting with Webhooks by Zapier → Catch Hook, copy the hook URL Zapier gives you, and register it with POST /v1/webhooks. Set includeResult so the extracted fields ride along with the event and the Zap needs no follow-up call. The response contains the signing secret once — store it now if you plan to verify signatures — and the workspace owners and admins get an email saying a new destination was added.

    curl -s -X POST https://api.parseforme.com/v1/webhooks \
      -H "Authorization: Bearer pfm_live_…" \
      -H "Content-Type: application/json" \
      -d '{
            "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
            "events": ["document.parsed", "document.failed"],
            "includeResult": true
          }'
  5. Verify the signature (Catch Raw Hook)

    A plain Catch Hook trusts whoever knows the URL. To check the delivery really came from ParseForMe, use Catch Raw Hook instead — it keeps the raw body — and add a Code by Zapier (JavaScript) step that recomputes the HMAC over t + "." + the raw body and compares it to the v1 value in X-ParseForMe-Signature. Reject anything older than 300 seconds. Deliveries always come from 46.62.162.196, which you can allowlist as a second check.

    const crypto = require('node:crypto');
    
    // Header: X-ParseForMe-Signature: t=<unix seconds>,v1=<hex hmac-sha256>
    // Signed payload is t + "." + the RAW request body (parse JSON afterwards).
    function verifyParseForMe(rawBody, header, secret) {
      const parts = header.split(',').map((p) => p.trim());
      const t = parts.find((p) => p.startsWith('t='))?.slice(2);
      // Two v1 entries appear while a secret is rotating — either may match.
      const sent = parts.filter((p) => p.startsWith('v1=')).map((p) => p.slice(3));
      if (!t || sent.length === 0) return false;
      if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // 5-minute tolerance
    
      const expected = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
      return sent.some(
        (sig) =>
          sig.length === expected.length &&
          crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)),
      );
    }
  6. Send a test event before you turn the Zap on

    POST /v1/webhooks/{id}/test sends a synthetic document.parsed to your endpoint and tells you what it answered, so you can finish Zapier’s “test trigger” step without waiting for a real document. A 2xx within 10 seconds counts as delivered; on a real event a 5xx, a 408, 425 or 429, or no answer at all is retried with backoff for about 13 hours, and any other answer is not.

    curl -s -X POST https://api.parseforme.com/v1/webhooks/1f8c…/test \
      -H "Authorization: Bearer pfm_live_…"
    
    # {"delivered":true,"status":200}
  7. Keep a polling backstop

    Webhooks are the fast path, not the only one. GET /v1/documents returns documents newest first by creation time, each with a stable id, so a scheduled run picks up anything a delivery missed — and two things only polling sees: an event lost before it was queued (delivery is at-most-once), and a document whose event you missed while an endpoint was disabled. since= filters that same creation time — not the parse time — so set it a little before your last successful check and keep the window wide enough to cover a slow parse: a document created before your watermark but parsed after it will not reappear. Ask for up to 100 with limit=; the response is items only, with no cursor to follow. Deduplicate on the document id.

    GET /v1/documents?status=parsed&since=2026-09-02T08:00:00Z&limit=50
    Host: api.parseforme.com
    Authorization: Bearer pfm_live_…
    
    # → { "items": [ { "id": "8f14e45f-…", "status": "parsed", "kind": "invoice" } ] }
  8. Map the fields you care about

    GET /v1/document-types returns the nine document kinds and the fields each one extracts, so your mapping step can be built against the real field names instead of a guess. Parsed values arrive under result.fields, with a matching entry in result.confidence — route anything you want a human to check on that, rather than on a total.

    curl -s https://api.parseforme.com/v1/document-types \
      -H "Authorization: Bearer pfm_live_…"

Frequently asked questions

Is ParseForMe a listed Zapier app?

Not yet. It connects through Webhooks by Zapier — a Custom Request action to send documents, and a Catch Hook trigger to receive parsed fields.

Which files can a Zap send?

PDF, DOCX, PNG, JPEG, TIFF and WebP, up to 20 MB each. The Zap sends the file’s https URL and ParseForMe fetches it.

What happens if a Zap runs twice on the same file?

Send an Idempotency-Key header built from something stable in the trigger. A repeat call returns the same document instead of parsing — and paying — twice.

Do I have to build parsing rules or a template first?

No. ParseForMe detects the document type and extracts its fields; you map those fields into the rest of your Zap once.

Zapier is a trademark of Zapier, Inc. ParseForMe is not affiliated with, endorsed by or sponsored by Zapier.

Try it on your own document

Drop a document to see the structured data come back.

Drop a document to try it — freeNo signup to start. Get 30 free tokens when you sign in.