Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Real-time OCR and data extraction API by Veryfi (https://veryfi.com). Extract structured data from receipts, invoices, bank statements, W-9s, purchase orders, bills of lading, and any other document. Use when you need to OCR documents, extract fields, parse receipts/invoices, bank statements, classify documents, detect fraud, or get raw OCR text from any document.
.claude/skills/veryfi-documents-ai/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-07 | ✗→✓ | ▲ Improved | — | — |
| case-15 | ✗→✓ | ▲ Improved | — | — |
Real-time OCR and data extraction API — extract structured data from receipts, invoices, bank statements, W-9s, purchase orders, and more, with document classification, fraud detection, and raw OCR text output.
> Get your API key: https://app.veryfi.com/api/settings/keys/ > Learn more: https://veryfi.com
For Receipts and Invoices:
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/documents/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@invoice.pdf"
Response:
json{ "id": 62047612, "created_date": "2026-02-19", "currency_code": "USD", "date": "2026-02-18 14:22:00", "document_type": "receipt", "category": "Meals & Entertainment", "is_duplicate": false, "vendor": { "name": "Starbucks", "address": "123 Main St, San Francisco, CA 94105" }, "line_items": [ { "id": 1, "order": 0, "description": "Caffe Latte Grande", "quantity": 1, "price": 5.95, "total": 5.95, "type": "food" } ], "subtotal": 5.95, "tax": 0.52, "total": 6.47, "payment": { "type": "visa", "card_number": "1234" }, "ocr_text": "STARBUCKS\n123 Main St...", "img_url": "https://scdn.veryfi.com/documents/...", "pdf_url": "https://scdn.veryfi.com/documents/..." }
For Bank Statements:
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/bank-statements/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@bank-statement.pdf"
Response:
json{ "id": 4820193, "created_date": "2026-02-19T12:45:00.000000Z", "bank_name": "Chase", "bank_address": "270 Park Avenue, New York, NY 10017", "account_holder_name": "Jane Doe", "account_holder_address": "456 Oak Ave, San Francisco, CA 94110", "account_number": "****7890", "account_type": "Checking", "routing_number": "021000021", "currency_code": "USD", "statement_date": "2026-01-31", "period_start_date": "2026-01-01", "period_end_date": "2026-01-31", "beginning_balance": 12500.00, "ending_balance": 11835.47, "accounts": [ { "number": "****7890", "beginning_balance": 12500.00, "ending_balance": 11835.47, "summaries": [ { "name": "Total Deposits", "total": 3200.00 }, { "name": "Total Withdrawals", "total": 3864.53 } ], "transactions": [ { "order": 0, "date": "2026-01-05", "description": "Direct Deposit - ACME Corp Payroll", "credit_amount": 3200.00, "debit_amount": null, "balance": 15700.00, "category": "Income" }, { "order": 1, "date": "2026-01-12", "description": "Rent Payment - 456 Oak Ave", "credit_amount": null, "debit_amount": 2800.00, "balance": 12900.00, "category": "Housing" }, { "order": 2, "date": "2026-01-20", "description": "PG&E Utility Bill", "credit_amount": null, "debit_amount": 1064.53, "balance": 11835.47, "category": "Utilities" } ] } ], "pdf_url": "https://scdn.veryfi.com/bank-statements/...", "img_url": "https://scdn.veryfi.com/bank-statements/..." }
bash# Visit API Auth Credentials page https://app.veryfi.com/api/settings/keys/
Save your API keys:
bashexport VERYFI_CLIENT_ID="your_client_id_here" export VERYFI_USERNAME="your_username_here" export VERYFI_API_KEY="your_api_key_here"
Recommended: Use environment variables (most secure):
json5{ skills: { entries: { "veryfi-documents-ai": { enabled: true, // Keys loaded from environment variables: // VERYFI_CLIENT_ID, VERYFI_USERNAME, VERYFI_API_KEY }, }, }, }
Alternative: Store in config file (use with caution):
json5{ skills: { entries: { "veryfi-documents-ai": { enabled: true, env: { VERYFI_CLIENT_ID: "your_client_id_here", VERYFI_USERNAME: "your_username_here", VERYFI_API_KEY: "your_api_key_here", }, }, }, }, }
Security Note: If storing API keys in ~/.openclaw/openclaw.json:
chmod 600 ~/.openclaw/openclaw.jsonbashcurl -X POST "https://api.veryfi.com/api/v8/partner/documents/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@invoice.pdf"
When your agent already has the document as base64-encoded content (e.g., received via API, email attachment, or tool output), use file_data instead of uploading a file:
bash# Encode the file first BASE64_DATA=$(base64 -i invoice.pdf) curl -X POST "https://api.veryfi.com/api/v8/partner/documents/" \ -H "Content-Type: application/json" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -d "{ \"file_name\": \"invoice.pdf\", \"file_data\": \"$BASE64_DATA\" }"
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/documents/" \ -H "Content-Type: application/json" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -d '{ "file_url": "https://example.com/invoice.pdf" }'
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/any-documents/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@passport.jpg" \ -F "blueprint_name=passport"
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/checks/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@check.jpg"
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/w9s/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@w9.pdf"
W-2 and W-8 forms do not have dedicated endpoints. Use the any-documents endpoint with the appropriate blueprint:
bash# W-2 curl -X POST "https://api.veryfi.com/api/v8/partner/any-documents/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@w2.pdf" \ -F "blueprint_name=w2" # W-8 curl -X POST "https://api.veryfi.com/api/v8/partner/any-documents/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@w8.pdf" \ -F "blueprint_name=w8"
> Note: W-2 and W-8 appear as classification types (via /classify/) but their extraction is handled through the Any Document endpoint. Do not POST to /api/v8/partner/w2s/ or /api/v8/partner/w8s/ — those endpoints do not exist.
All extraction endpoints return an ocr_text field in the response containing the raw text content of the document as a plain string. This is useful when you want to process the text yourself or pass it to an LLM.
bash# Extract and pull ocr_text with jq curl -X POST "https://api.veryfi.com/api/v8/partner/documents/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@document.pdf" \ | jq '.ocr_text'
> Note: ocr_text is plain text, not markdown. If you need markdown-formatted output, pass ocr_text to an LLM for reformatting after extraction.
Identify the document type without full data extraction. Useful for routing documents to the correct processing endpoint, pre-filtering uploads, or bulk sorting.
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/classify/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@document.pdf"
> Note: By default, the API classifies against 15 built-in types. You can also pass a document_types array with custom classes (see example below).
Response:
json{ "id": 81023456, "document_type": { "score": 0.97, "value": "invoice" } }
Default document types: receipt, invoice, purchase_order, bank_statement, check, w2, w8, w9, statement, contract, credit_note, remittance_advice, business_card, packing_slip, other.
To classify against custom types, pass a document_types array:
bashcurl -X POST "https://api.veryfi.com/api/v8/partner/classify/" \ -H "Content-Type: multipart/form-data" \ -H "Client-Id: $VERYFI_CLIENT_ID" \ -H "Authorization: apikey $VERYFI_USERNAME:$VERYFI_API_KEY" \ -F "file=@document.pdf" \ -F 'document_types=["lease_agreement", "utility_bill", "pay_stub"]'
Get element coordinates for layout analysis:
bash-F "bounding_boxes=true" -F "confidence_details=true"
| Document Type | Endpoint | Notes | |---------------|----------|------------| | Receipts & Invoices | /api/v8/partner/documents/ | use for receipts/invoices/purchase orders | | Bank Statements | /api/v8/partner/bank-statements/ | use for Bank statements | | Checks | /api/v8/partner/checks/ | use for bank checks (cheques in Canada) | | W-9s | /api/v8/partner/w9s/ | W9 forms | | W-2s / W-8s | /api/v8/partner/any-documents/ | Use blueprint_name=w2 or blueprint_name=w8 | | Any Document | /api/v8/partner/any-documents/ | Use to extract data from any document; list of blueprints provided below | | Classify | /api/v8/partner/classify/ | Identify document type without full extraction |
List of available blueprints: | blueprint_name | Document Type | |---------------|----------| | passport | Passport US or International | | incorporation_document | Certificate of Company Incorporation | | us_driver_license | US Driver's License | | uk_drivers_license | UK Driver's Licence | | us_health_insurance_card | US Health Insurance Card | | prescription_medication_label | Prescription Medication Label | | medication_instructions | Medication Instructions | | vision_prescription | Vision Prescription | | auto_insurance_card | Auto Insurance Card | | restaurant_menu | Restaurant Menu | | drinks_menu | Drinks Menu | | product_nutrition_facts | Product Nutrition Facts Label | | goods_received_note | Goods Received Note | | vendor_statement | Vendor Statement | | flight_itinerary | Flight Itinerary | | bill_of_lading | Bill of Lading | | air_waybill | Air Waybill | | freight_invoice | Freight Invoice | | shipping_label | Shipping Label | | vehicle_registration | Vehicle Registration | | work_order | Work Order | | settlement_letter | Settlement Letter | | construction_estimate | Construction Estimate | | diploma | Diploma or Degree Certificate | | price_sheet | Price Sheet | | mortgage_application_form | Mortgage Application Form | | lab_test_request_form | Lab Test Request Form | | construction_snapshot | Construction Snapshot | | medical_prescription_list | Medical Prescription List | | v5c | UK Vehicle Registration Certificate (V5C) | | bank_account_verification_letter | Bank Account Verification Letter | | annual_mortgage_statement | Annual Mortgage Statement | | investment_account_statement | Investment Account Statement | | certificate_of_good_standing | Certificate of Good Standing | | w2 | IRS W-2 Wage and Tax Statement | | w8 | IRS W-8 Certificate of Foreign Status |
Missing document type? If document type (blueprint) you need to extract data from is missing, create one here: https://app.veryfi.com/inboxes/anydocs?tab=blueprints
Bounding Boxes & Confidence:
-F "bounding_boxes=true" for element coordinates-F "confidence_details=true" for per-field confidence scoresSupported Inputs:
file — multipart file uploadfile_url — publicly accessible URLfile_data — base64-encoded content (send as JSON body with file_name + file_data fields)/api/v8/partner/documents/)json{ "id": 62047612, "created_date": "2026-02-19T00:00:00.000000Z", "updated_date": "2026-02-19T00:00:05.000000Z", "currency_code": "USD", "date": "2026-02-18 14:22:00", "due_date": "2026-03-18", "document_type": "receipt", "category": "Meals & Entertainment", "is_duplicate": false, "is_document": true, "invoice_number": "INV-2026-001", "account_number": "ACCT-12345", "order_date": "2026-02-18", "delivery_date": null, "vendor": { "name": "Starbucks", "address": "123 Main St, San Francisco, CA 94105", "phone_number": "+1 415-555-0100", "email": null, "vat_number": null, "reg_number": null }, "bill_to": { "name": "Jane Doe", "address": "456 Oak Ave, San Francisco, CA 94110" }, "ship_to": { "name": null, "address": null }, "line_items": [ { "id": 1, "order": 0, "description": "Caffe Latte Grande", "quantity": 1, "price": 5.95, "total": 5.95, "tax": 0.52, "tax_rate": 8.75, "discount": null, "type": "food", "sku": null, "upc": null, "category": "Meals & Entertainment", "section": null, "date": null, "start_date": null, "end_date": null } ], "tax_lines": [ { "order": 0, "name": "Sales Tax", "rate": 8.75, "total": 0.52, "base": 5.95 } ], "subtotal": 5.95, "tax": 0.52, "tip": 0.00, "discount": 0.00, "total": 6.47, "payment": { "type": "visa", "card_number": "1234" }, "reference_number": null, "notes": null, "img_url": "https://scdn.veryfi.com/documents/...", "pdf_url": "https://scdn.veryfi.com/documents/...", "ocr_text": "STARBUCKS\n123 Main St...", "meta": { "total_pages": 1, "processed_pages": 1, "fraud": { "score": 0.01, "color": "green", "decision": "Not Fraud", "types": [] } } }
/api/v8/partner/checks/)json{ "id": 9301847, "created_date": "2026-02-19T00:00:00.000000Z", "updated_date": "2026-02-19T00:00:03.000000Z", "amount": 1500.00, "amount_text": "One Thousand Five Hundred and 00/100", "check_number": "4021", "date": "2026-02-15", "currency_code": "USD", "check_type": "personal_check", "payer_name": "John Smith", "payer_address": "789 Elm St, Austin, TX 78701", "receiver_name": "Acme Plumbing LLC", "receiver_address": null, "bank_name": "Wells Fargo", "bank_address": "420 Montgomery St, San Francisco, CA 94104", "memo": "Invoice #2026-038", "is_signed": true, "micr": { "routing_number": "121000248", "account_number": "****5678", "serial_number": "4021", "raw": "⑆121000248⑆ ****5678⑈ 4021", "branch": null, "institution": null }, "fractional_routing_number": "12-1/1200", "routing_from_fractional": "121000248", "endorsement": { "is_endorsed": true, "is_signed": true, "mobile_or_remote_deposit": { "checkbox": false, "instructions": false } }, "handwritten_fields": ["amount", "amount_text", "date", "receiver_name", "memo"], "fraud": { "score": 0.02, "color": "green", "types": [], "pages": [ { "is_lcd": { "score": 0.98, "value": false }, "ai_generated": { "score": 0.99, "value": false }, "four_corners_detected": true } ] }, "img_thumbnail_url": "https://scdn.veryfi.com/checks/...", "pdf_url": "https://scdn.veryfi.com/checks/..." }
/api/v8/partner/bank-statements/)json{ "id": 4820193, "created_date": "2026-02-19T12:45:00.000000Z", "updated_date": "2026-02-19T12:45:10.000000Z", "bank_name": "Chase", "bank_address": "270 Park Avenue, New York, NY 10017", "account_holder_name": "Jane Doe", "account_holder_address": "456 Oak Ave, San Francisco, CA 94110", "account_number": "****7890", "account_type": "Checking", "routing_number": "021000021", "currency_code": "USD", "statement_date": "2026-01-31", "period_start_date": "2026-01-01", "period_end_date": "2026-01-31", "beginning_balance": 12500.00, "ending_balance": 11835.47, "minimum_due": null, "due_date": null, "accounts": [ { "number": "****7890", "beginning_balance": 12500.00, "ending_balance": 11835.47, "summaries": [ { "name": "Total Deposits", "total": 3200.00 }, { "name": "Total Withdrawals", "total": 3864.53 } ], "transactions": [ { "order": 0, "date": "2026-01-05", "posted_date": "2026-01-05", "description": "Direct Deposit - ACME Corp Payroll", "credit_amount": 3200.00, "debit_amount": null, "balance": 15700.00, "category": "Income", "vendor": "ACME Corp" }, { "order": 1, "date": "2026-01-12", "posted_date": "2026-01-12", "description": "Rent Payment - 456 Oak Ave", "credit_amount": null, "debit_amount": 2800.00, "balance": 12900.00, "category": "Housing", "vendor": null } ] } ], "fraud": { "score": 0.01, "color": "green", "types": [] }, "pdf_url": "https://scdn.veryfi.com/bank-statements/...", "img_thumbnail_url": "https://scdn.veryfi.com/bank-statements/..." }
Important: Documents uploaded to Veryfi are transmitted to https://api.veryfi.com and processed on AWS servers.
Before uploading sensitive documents:
Best practices:
"your_api_key_here" in examplesVeryfi enforces per-account rate limits. Exact limits depend on your plan tier.
General guidance:
400 Bad Request:
file, file_url, or file_data (for base64)file_data, send as a JSON body (not multipart) with file_name and file_data fieldsmessage field in the JSON response for the specific error detail401 Unauthorized:
Client-Id, VERYFI_USERNAME, or VERYFI_API_KEY is incorrect or expiredAuthorization header format is exactly apikey USERNAME:API_KEY (no extra spaces)413 Payload Too Large:
429 Too Many Requests:
500 / 5xx Server Error:
Missing Confidence Scores:
confidence_details=true to the request to include score and ocr_score fields in the responsebounding_boxes=true to also get bounding_box and bounding_region coordinatesW-2 / W-8 endpoint 404:
/w2s/ or /w8s/ endpoints — use /any-documents/ with blueprint_name=w2 or blueprint_name=w8VERYFI_CLIENT_ID, VERYFI_USERNAME, and VERYFI_API_KEY in environment variables rather than hardcoding themconfidence_details=true and bounding_boxes=true when you need per-field accuracy scores or element coordinates/classify/ and route to the appropriate extraction endpointhttps://app.veryfi.com/inboxes/anydocs?tab=blueprintsocr_text in the response gives you raw extracted text — pass it to an LLM if you need markdown or further processingfile_name so Veryfi can infer the file type correctly| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +59 percentage points is the difference between those two pass rates over the 20 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.