What you need
- The Python SDK and an API key, set up as in Cookbooks.
boto3, with AWS credentials that can list and read the documents and write the results.- An Amazon S3 bucket of PDFs. Signed URLs from Google Cloud Storage or Azure Blob Storage work the same way.
Build it
1
Set up the clients
This code creates the Pulse and S3 clients, and names the bucket and its folders.
2
Sign a URL for each document
This code signs a download URL, valid for 48 hours, for each PDF in the folder.Pulse fetches each URL when its job runs, up to 48 hours after you send the batch, so sign with credentials that last that long. A URL signed with temporary credentials, such as an assumed role’s, stops working when they expire.
3
Send the batch
This code sends the URLs in batches of up to 1,000 and keeps each A batch always runs async, and each URL becomes its own parse job. A URL that doesn’t return the document when its job runs, such as one whose signature has expired, fails only its own job.
batch_id.4
Write each result as its job ends
drain reads a batch’s manifest, the list of its jobs that have ended, and passes each new job to handle, which writes its result to the bucket.5
Run until every batch ends
This loop drains each batch in turn. A brief
429 or 5xx error stops drain; the loop waits and starts it again.handled makes sure no result is read twice and none is skipped when drain starts again, even after a restart if you store it with the batch ids.How it works
The id each step hands to the next: On each pass,drain reads the batch’s status and the manifest:
The manifest’s entries never move, so drain follows each page’s Link header to the next page, then asks for the last page again until the batch ends.
Each result is read once, so the recipe also works where your organization deletes a result the first time it’s read.
Edge cases
Mapping results to objects
Mapping results to objects
A manifest entry names its
parse_id, not its URL, and the result’s history.file_name holds only the file’s name, which can repeat across folders. To file results by object key, or to retry one object, send one async /parse per object and store each parse_id with its key.Keeping results only in your bucket
Keeping results only in your bucket
Add
"storage": {"save": False} to CONFIG. Each result is then deleted 24 hours after its batch ends, or sooner if your organization sets a 1-hour retention. The free plan can’t turn saving off.A batch that ends failed or canceled
A batch that ends failed or canceled
A batch ends
failed when it isn’t done within 48 hours of being sent, or when it’s interrupted. After either, or after you cancel a batch, some of its jobs can still end: run drain once more a few minutes later, with the same handled, to collect them. An interrupted batch can also leave documents that never ran; to find those, track each object with its own parse_id, as above.A public folder
A public folder
If anyone can list and read the folder, send it as
folder_url instead of signing a URL for each document.More steps per document
More steps per document
To extract from each document as well, start the extract from a
parse.completed webhook. Then read each parse in handle only after its extract has ended, in case your organization deletes a result the first time it’s read.Next steps
Batch
Sources, statuses, limits and the manifest.
Webhooks
Get a signed event as a job’s status changes.