Tag each submission with your ids
POST /v1/parse takes your ids as form fields. Both are recorded with the job and echoed back; neither changes
how the documents are read.
Open a deal for every job, failed ones included
Every job carriesintake, whatever its status: how the packet came in and what it declared. It is on
GET /v1/jobs/{job_id}, on every row of GET /v1/jobs, and in the payload of every job event, job.failed
included. A job that failed before anything could be read (an unreadable file, a run that timed out) still
names its broker, its email and its files, so you can open the deal and ask for better documents.
intake never carries a file’s contents or an email’s body. The merchant’s details as read from the documents
are in the result (submission_packet.submission_intelligence.company_profile, applications[].fields), once the
job has one.
Fetch the original files
sha256 matches), with
Content-Disposition: attachment and the content type it was declared with. Both calls need jobs:read, and
answer 404 for another tenant’s job, an erased job or a position the job does not have. For an emailed job the
files are the email’s attachments that were taken (PDF, PNG and JPEG). The message itself is
GET /v1/emails/{intake.email.email_id}/raw, as received, unless its mailbox turned store_raw_email off.
Follow every email of a deal
An emailed deal is a thread.intake.email.thread_id names it, and GET /v1/emails/threads/{thread_id} lists
every email of it in order (the submission, replies, forwards, questions), each with its outcome and job. To track
every email as it arrives, ignored ones included, subscribe an endpoint to
email.received; tag emails with your own labels to file them. See
Emails and threads.
Never miss a job
Webhooks are the primary channel: each job’s final event is written with its status, and retried for about 23 hours (the schedule). Two more tools close the gaps:- Polling:
GET /v1/jobs?finished_since=lists every job that finished since a time, oldest finish first, paged withcursor. Each finished job appears once across the pages, and a job erased between two pages does not break the cursor. - Re-sending: a delivery that died (your endpoint was down) can be sent again, one at a time or every dead
one since a time (re-send). It is the same event, with the same
X-Parser-Event-Id.
Erase an end user’s data
end_user_id is erased exactly as DELETE /v1/jobs/{job_id} erases one:
its request and result, its input files, the cached reads of its documents, the model answers it paid for, its
metering, email thread entries, the emails that fed it with their raw
messages, and webhook events. Each erasure is in the audit log (job.delete, with the
end_user_id). A job still queued or running is not erased but listed in still_running: call again once it
ends; the call is safe to repeat. It needs jobs:delete and never touches another tenant’s jobs.
Jobs that came in by email carry no end_user_id (an email declares none): erase those one by one with
DELETE /v1/jobs/{job_id}.