https://txtfetch.com/integrations/zapier/
Extract text in a Zap, no txtfetch app required.
There is no txtfetch app in the Zapier directory. Webhooks by Zapier's Custom Request action calls the same API directly, and a link works better than a file step ever would.
the-problem
A Zap that needs text out of an incoming document usually starts from a Google Drive file, a Gmail attachment, or a form upload. Zapier's steps pass those around as file objects. Forwarding one to a Custom Request action as binary data is fiddly and easy to get wrong. Zaps also run on a fixed step timeout. A document that takes a while to OCR can fail the step before it ever gets a result back.
how-to-wire-it-up
txtfetch has no Zapier integration listed in the app directory. Webhooks by Zapier's Custom Request action reaches the same REST endpoint a curl command would, with no app to install first. Most upstream steps already expose a shareable link for the file — a Google Drive share link, a Gmail attachment URL. Pass that as the url query parameter, instead of trying to forward the file's bytes. For a document that's large or slow, add async and webhook_url to the same request. Then let a second Zap start from a Catch Hook trigger when the result is ready.
- Pass ?url= with a file's existing share link, so the Custom Request action never handles binary file data.
- Automatic OCR covers scanned PDFs and photographed forms, with no separate OCR app needed in the Zap.
- Async mode returns a job_id immediately, so a slow extraction never times out the Custom Request step.
- A Catch Hook trigger on a second Zap picks up the webhook_url callback and continues the automation from there.
- Idempotency-Key support keeps a Zapier auto-replay from re-running and re-billing the same extraction.
pass-a-link-not-a-file
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.pdf" \
-H "Authorization: Bearer $TXTFETCH_KEY"import os
import requests
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
params={"url": "https://example.com/report.pdf"},
)
print(r.json()["extracted_text"])const endpoint = new URL("https://api.txtfetch.com/v1/extract");
endpoint.searchParams.set("url", "https://example.com/report.pdf");
const res = await fetch(endpoint, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
});
const { extracted_text } = await res.json();
console.log(extracted_text);package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
endpoint, err := url.Parse("https://api.txtfetch.com/v1/extract")
if err != nil {
panic(err)
}
q := endpoint.Query()
q.Set("url", "https://example.com/report.pdf")
endpoint.RawQuery = q.Encode()
req, err := http.NewRequest("POST", endpoint.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result extractResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
fmt.Println(result.ExtractedText)
}{
"status": "success",
"extracted_text": "..."
}large-or-slow-documents
POST /v1/extract returns 202 with a job_id whenever the document is large or slow to process, or whenever async=true is set. Poll GET /v1/extract/{job_id} for the result, or set webhook_url and have txtfetch push it instead. No single request on this page is safe to assume will always finish synchronously.
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.pdf&async=true" \
-H "Authorization: Bearer $TXTFETCH_KEY"
# {"status": "processing", "job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}curl "https://api.txtfetch.com/v1/extract/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Authorization: Bearer $TXTFETCH_KEY"
# {"status": "processing", "job_id": "..."} while running, then the same
# {"status": "success", "extracted_text": "...", "metadata": {...}} shape
# POST /v1/extract would have returned synchronously.curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.pdf" \
-H "Authorization: Bearer $TXTFETCH_KEY" \
--data-urlencode "webhook_url=https://example.com/webhooks/txtfetch"setup-steps
- Add a Webhooks by Zapier action and choose Custom Request.
- Set Method to POST.
- Set URL to https://api.txtfetch.com/v1/extract, then add url as a query string parameter with the document's link.
- Under Headers, add Authorization with the value Bearer, followed by your API key.
- For a large document, add async set to true and webhook_url set to a second Zap's Catch Hook address.
- Test the action. Zapier shows extracted_text in the returned data, ready to map into the next step.
faq
- Is there a txtfetch app in the Zapier directory?
- No. txtfetch has no listed Zapier app or connector. Webhooks by Zapier's Custom Request action reaches the same REST API with no app install needed.
- How do I send a file from a Zap without a txtfetch app?
- Use the file's share link from the upstream step — Google Drive, Dropbox, and Gmail attachments all expose one. Pass it as the url query parameter, rather than forwarding the file itself.
- Can a Zap wait for a slow OCR job without timing out?
- Yes. Add async=true and webhook_url to the request, and end the first Zap there. Start a second Zap from a Catch Hook trigger when the callback arrives.
- How does a Zap tell a failed extraction from a successful one?
- Check the status field in the response. A failed request still returns a typed error.code instead of extracted_text, so a Filter step can catch it before the Zap continues.
related-reading
other-integrations