Skip to main content
RapidDev - Software Development Agency
bubble-integrationsBubble API Connector

Receipt Bank (now Dext)

Receipt Bank rebranded to Dext in 2021 — the same OCR expense capture product, now at api.dext.com. Connecting Bubble to Dext requires the API Connector for receipt uploads and a Backend Workflow polling loop because Dext's OCR is asynchronous: you upload a receipt image, receive a document ID, then repeatedly check the document status until it changes from 'processing' to 'processed'. Only then can you read the extracted vendor, amount, date, and category fields. API access may require a specific Dext plan tier.

What you'll learn

  • That Receipt Bank and Dext are the same product — the rebrand in 2021 moved all API endpoints to api.dext.com
  • Why Dext's OCR is asynchronous and why a Backend Workflow polling loop is mandatory, not optional
  • How to upload receipt images via Bubble's API Connector using multipart/form-data format
  • How to build a Backend Workflow polling loop that retries GET /documents/{id} with 5-second waits until processing completes
  • How to extract vendor, amount, date, and category from the processed document response and save them to Bubble's database
  • Why API access may require a specific Dext plan tier and how to confirm your account has API access
  • How multi-client accounting firms should structure their Bubble integration using per-client API keys
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate23 min read3–5 hoursFinance & AccountingLast updated July 2026RapidDev Engineering Team
TL;DR

Receipt Bank rebranded to Dext in 2021 — the same OCR expense capture product, now at api.dext.com. Connecting Bubble to Dext requires the API Connector for receipt uploads and a Backend Workflow polling loop because Dext's OCR is asynchronous: you upload a receipt image, receive a document ID, then repeatedly check the document status until it changes from 'processing' to 'processed'. Only then can you read the extracted vendor, amount, date, and category fields. API access may require a specific Dext plan tier.

Quick facts about this guide
FactValue
ToolDext (formerly Receipt Bank)
CategoryFinance & Accounting
MethodBubble API Connector
DifficultyIntermediate
Time required3–5 hours
Last updatedJuly 2026

Dext on Bubble: The Async OCR Pattern You Must Know

If you searched for 'Receipt Bank API Bubble' and landed here, you are in the right place. Receipt Bank rebranded to Dext in 2021. The product is identical — same OCR engine, same bank connections, same accounting integrations — but the brand name, marketing site, and all API endpoints moved to dext.com. The API base URL is now https://api.dext.com/v1.

The most important thing to understand about the Dext API before writing a single line of configuration: the OCR processing is asynchronous. Every tutorial that shows 'upload receipt → get data back immediately' is describing a different API. Dext's workflow is:

1. Upload receipt image (POST /documents) → receive a document_id immediately 2. Wait for OCR engine to process (typically 10–90 seconds) 3. Poll GET /documents/{document_id} until status = 'processed' 4. Read extracted fields from the processed document

Step 3 is where most Bubble builders get stuck. You cannot do this in a standard Bubble workflow because Bubble workflows are not designed for loop-with-delay patterns. You need a Backend Workflow that: - Calls GET /documents/{document_id} - Checks the status field - If status is not 'processed': waits 5 seconds and runs itself again (recursive call) - If status is 'processed': extracts the fields and saves to Bubble's database - If 15 attempts pass without 'processed' status: shows a timeout error

Backend Workflows are only available on paid Bubble plans.

The second thing to know: API access is not automatically available on all Dext account tiers. Before spending time on integration, confirm that your Dext account has API access enabled. Log into your Dext account, look for Settings → Integrations or Developer section — if you do not see an API key option, you may need to contact Dext support or upgrade your plan.

With those two facts clear, the integration itself is straightforward: one upload endpoint, one status endpoint, one set of Private headers, and a polling loop. Let's build it.

Integration method

Bubble API Connector

Bubble API Connector for receipt uploads (POST /documents) and status polling (GET /documents/{id}); Backend Workflow polling loop required for asynchronous OCR status checking (paid Bubble plan required).

Prerequisites

  • A Dext account with API access enabled — log into your Dext account and look for an API key in Settings; if not visible, contact Dext support as API access may require a specific plan tier
  • A Bubble account on a paid plan — the async polling Backend Workflow is essential and not available on Bubble's free plan
  • The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → 'API Connector' by Bubble)
  • Your Dext API key — generated from your Dext account Settings once API access is confirmed
  • A Bubble data type to store extracted expense data (vendor, amount, date, category, document_id, status)
  • Understanding that OCR processing is asynchronous — there is no instant data extraction; the polling loop waits 10–90 seconds for results

Step-by-step guide

1

Confirm API Access and Configure the API Connector

Before configuring anything in Bubble, verify that your Dext account has API access. This step saves significant frustration — a 403 response from a correctly configured API call almost always means API access is not enabled on your account tier, not that your configuration is wrong. Log into your Dext account at app.dext.com. Navigate to Settings (usually your account icon → Settings or via the main menu). Look for an 'Integrations', 'Developer', or 'API' section. If you see an API key option, copy your key. If you do not see this section, contact Dext support (support@dext.com) and ask them to enable API access on your account — mention that you are building a third-party integration and need developer API access. Once you have your API key, go to Bubble. Click the Plugins tab → Add plugins → search 'API Connector' (by Bubble) → Install. Click 'Add another API' and name it 'Dext'. Set the base URL to: https://api.dext.com/v1 Add a shared header: - Key: Authorization - Value: ApiKey [api_key] — note the format is 'ApiKey {key}', NOT 'Bearer {key}' - Enable the 'Private' checkbox — your API key stays on Bubble's servers and never reaches the browser IMPORTANT: The exact Authorization header format for Dext may be 'ApiKey {key}' or 'Bearer {key}' — this is a known gotcha. Check the current Dext API documentation at developers.dext.com before finalizing the format. Using the wrong prefix returns 401 even with a valid key. If you get 401 on your Initialize Call and the key is correct, try switching between 'ApiKey' and 'Bearer' prefixes. Save the API configuration. You are now ready to add specific API calls.

dext-api-connector-config.json
1{
2 "base_url": "https://api.dext.com/v1",
3 "shared_headers": [
4 {
5 "key": "Authorization",
6 "value": "ApiKey <your-dext-api-key>",
7 "private": true,
8 "note": "Verify exact prefix format (ApiKey vs Bearer) in current Dext API docs"
9 }
10 ]
11}

Pro tip: If you receive a 403 (not 401) on your first API call after confirming the correct key format, this means API access is blocked at the account tier level, not an auth error. 403 = forbidden (plan issue); 401 = unauthorized (credentials issue). Contact Dext support about 403 responses.

Expected result: The API Connector shows 'Dext' in your API list with one Private shared header. You are ready to add the upload and status-check calls.

2

Build the Receipt Upload API Call

The upload call sends a receipt image file to Dext and receives a document_id in return. The image must be sent as multipart/form-data — a standard file upload format that Bubble's API Connector supports. In your Dext API group, click 'Add a call'. Name it 'Upload Document'. - Method: POST - Path: /documents - Body type: Form-data (multipart) Add a form field: - Key: file - Type: File - Value: [document_file] — make this a parameter Add additional form fields that Dext may accept (verify in current documentation): - Key: original_filename - Value: [filename] — helps Dext identify the document type Set 'Use as' to Action (not Data) — you are submitting data, not reading it. Click 'Initialize call'. For the file parameter, you will need a real image file URL to initialize. Use a publicly accessible receipt image URL for testing (e.g., a JPEG URL from an image hosting service). Supply a filename like 'test-receipt.jpg'. A successful response returns a JSON object with a 'documents' array containing at least one object with an 'id' field — this is your document_id. Note the exact JSON path Bubble detects for the ID field. In Bubble, when a user uploads a file (using a File Uploader element), Bubble stores it as a URL in its file storage. You can pass this URL to the API call's file parameter — Bubble's API Connector can fetch and forward file URLs as multipart content. Build a simple 'Upload Receipt' button workflow: 1. Step 1: API call → Dext > Upload Document, with 'document_file' = File Uploader's value (the uploaded file URL) 2. Step 2: Make changes to a thing — create a new 'DextDocument' record in your database with: document_id = API response's id field, status = 'processing', uploaded_by = Current User, uploaded_at = Current date/time 3. Step 3: Schedule API Workflow → 'Poll Document Status' workflow (next step) to run in 5 seconds, passing the document_id Note: Dext may return the document ID in slightly different response paths across API versions. After Initialize Call succeeds, expand the response tree in Bubble's API Connector to confirm the exact field path.

dext-upload-document.json
1POST /documents
2Headers:
3 Authorization: ApiKey <private-api-key>
4 Content-Type: multipart/form-data
5
6Form fields:
7 file: <receipt-image-file>
8 original_filename: 'receipt-jan-2026.jpg'
9
10// Successful response:
11{
12 "documents": [
13 {
14 "id": "doc-uuid-12345",
15 "status": "processing",
16 "created_at": "2026-01-09T14:30:00Z",
17 "original_filename": "receipt-jan-2026.jpg"
18 }
19 ]
20}

Pro tip: Add a File Uploader element to your Bubble page and restrict accepted file types to image/jpeg, image/png, and application/pdf. Dext supports PDF invoices as well as image receipts. Restricting file types in the uploader prevents users from accidentally uploading incompatible file formats that will fail processing.

Expected result: After clicking 'Upload Receipt' with a test image, a new DextDocument record appears in your Bubble database with a document_id and status 'processing'. The Upload Document API call's Initialize Call completes with a document ID in the response.

3

Build the Async OCR Polling Backend Workflow

This is the core of the Dext integration — the polling loop that waits for OCR processing to complete. Dext's OCR takes 10–90 seconds depending on document complexity and queue volume. You cannot simply wait in a standard Bubble workflow because there is no 'wait' action in regular workflows (only in Backend Workflows). First, enable Backend Workflows: go to Settings → API → check 'This app exposes a Workflow API'. The Backend Workflows section now appears in your editor. Add the 'Poll Status' API call to your Dext API Connector: - Method: GET - Path: /documents/[document_id] — make document_id a text parameter - No body - Set 'Use as Data' The response includes a status field ('processing', 'processed', 'failed') and, when processed, the extracted data fields. Initialize this call by providing a real document_id from a previous upload test. You need an active document that has finished processing to capture the 'processed' response shape. Now build the Backend Workflow 'Dext_PollDocumentStatus': - Input parameters: document_id (Text), attempt_count (Number, default 0) Workflow steps: 1. Call API → Dext > Poll Status, with document_id = input document_id 2. Only when response status = 'processed': Make changes to DextDocument (where document_id = input) — set status = 'processed', vendor = response's supplier name field, amount = response's total_amount field, document_date = response's date field, category = response's category field 3. Only when response status = 'processing' AND attempt_count < 15: Schedule API Workflow → 'Dext_PollDocumentStatus', run in 5 seconds, pass document_id = same document_id, attempt_count = input attempt_count + 1 4. Only when attempt_count >= 15: Make changes to DextDocument — set status = 'timeout', show error to user via a Bubble page state or notification system The recursive call in Step 3 (scheduling itself with attempt_count + 1) creates the polling loop. Each iteration waits 5 seconds before checking again, for a maximum of 15 attempts (75 seconds total timeout). Note: Bubble's 'Schedule API workflow' action inside a Backend Workflow adds the scheduled call to a queue. The scheduling step itself completes instantly — the 5-second delay happens before the NEXT execution. The current workflow ends immediately after scheduling the next call, which is correct behavior.

dext-polling-backend-workflow.json
1// Backend Workflow: Dext_PollDocumentStatus
2// Input parameters: document_id (Text), attempt_count (Number)
3
4// Step 1: Call API Dext > Poll Status
5GET /documents/[document_id]
6Headers:
7 Authorization: ApiKey <private-api-key>
8
9// Successful 'processed' response:
10{
11 "document": {
12 "id": "doc-uuid-12345",
13 "status": "processed",
14 "supplier": { "name": "Whole Foods Market" },
15 "total_amount": 67.43,
16 "date": "2026-01-07",
17 "currency": "GBP",
18 "category": { "name": "Groceries" },
19 "tax_amount": 6.13
20 }
21}
22
23// Step 2 (Only when status = 'processed'):
24// Make changes to DextDocument:
25// status = 'processed'
26// vendor_name = Step 1 result's document supplier name
27// total_amount = Step 1 result's document total_amount
28// document_date = Step 1 result's document date
29// category = Step 1 result's document category name
30
31// Step 3 (Only when status = 'processing' AND attempt_count < 15):
32// Schedule API Workflow: Dext_PollDocumentStatus
33// document_id = workflow input document_id
34// attempt_count = workflow input attempt_count + 1
35// run at: Current date/time + 5 seconds
36
37// Step 4 (Only when attempt_count >= 15):
38// Make changes to DextDocument: status = 'timeout'

Pro tip: Set a maximum of 15 polling attempts (75 seconds total). If you make this number too high (e.g., 60 attempts = 5 minutes), a single stuck document consumes a large number of Backend Workflow executions that count toward your WU budget. 15 attempts is enough for all but unusually slow documents — if it times out, show the user a 'Processing taking longer than expected — check back in a few minutes' message.

Expected result: After uploading a receipt, the DextDocument record in Bubble updates from 'processing' to 'processed' within 10–90 seconds. The vendor_name, total_amount, document_date, and category fields are automatically populated from Dext's OCR extraction without any manual data entry.

4

Display Extracted Data and Build the Review UI

Once the polling workflow has stored the extracted data in your Bubble database, you need to show it to the user for review. Build a 'Pending Documents' Repeating Group and a document detail view that shows the extracted fields for approval or correction. Create a 'Pending Expenses' page or section in your Bubble app. Add a Repeating Group with: - Data source: Search for DextDocuments where uploaded_by = Current User, sorted by uploaded_at (newest first) - Type of content: DextDocument Inside the Repeating Group, show: - A thumbnail of the original receipt (store the file URL in your DextDocument record) - Document status (show a spinner or 'Processing...' badge while status = 'processing') - Vendor name (from OCR extraction) - Amount and currency - Date - Category (as a dropdown for correction if needed) For the spinner while processing: add a Conditional to show/hide elements based on the DextDocument's status field. Show a loading indicator when status = 'processing', show the extracted data when status = 'processed', show an error message when status = 'timeout' or 'failed'. For auto-refresh while processing: add a page data workflow that triggers every 3 seconds (using Bubble's 'Do every X seconds' trigger) and refreshes the Repeating Group's data source. Only show this trigger when at least one DextDocument for the current user has status = 'processing'. This way, users see the data appear automatically when OCR completes without needing to reload the page. For correction: wrap the extracted fields in editable inputs (Text inputs, Dropdowns) so users can fix OCR errors before approval. A 'Submit Expense' button saves the user-confirmed values to a final Expense record. For multi-client accounting firms: add a 'Client' selector at the top of the page. Store a Dext API key per Client in your Clients data type. When an accountant selects a client, the upload and polling workflows use that client's API key — not a single shared key. Store keys as Private fields in the Clients data type with appropriate Privacy Rules.

dext-review-ui-logic.json
1// DextDocument data type fields:
2// - document_id (Text)
3// - status (Text: 'processing' | 'processed' | 'timeout' | 'failed')
4// - vendor_name (Text, from OCR)
5// - total_amount (Number, from OCR)
6// - amount_currency (Text)
7// - document_date (Date, from OCR)
8// - category (Text, from OCR)
9// - tax_amount (Number, from OCR)
10// - original_file_url (Text)
11// - uploaded_by (User)
12// - uploaded_at (Date)
13// - user_approved (Yes/No, default no)
14// - user_notes (Text)
15
16// Repeating Group data source:
17// Search for DextDocuments:
18// Constraint: uploaded_by = Current User
19// Sort by: uploaded_at (descending)
20
21// Conditional: show 'Processing...' spinner
22// When: current cell's DextDocument's status = 'processing'
23// Show: loading-spinner-group
24// Hide: extracted-data-group
25
26// Auto-refresh: Do every 3 seconds
27// Only when: Search for DextDocuments (status='processing', uploaded_by=Current User):count > 0
28// Action: Refresh Group: repeating-group-documents

Pro tip: Add a 'Corrected by user' Yes/No field to your DextDocument type. When a user edits an OCR-extracted field (vendor, amount, category), set this flag to 'yes'. Use this for quality tracking — if many documents are corrected for a specific field, it suggests Dext's OCR accuracy for that document type is lower than expected and worth investigating with Dext support.

Expected result: The Pending Expenses page shows a list of uploaded receipts with their processing status. Documents showing 'Processing...' automatically update to display extracted data within seconds of Dext completing OCR. Users can review, correct if needed, and submit expenses.

5

Apply Privacy Rules and Verify the Full Upload-to-Extract Flow

Before going live, apply Bubble Privacy Rules to restrict access to expense documents, and run a complete end-to-end test of the upload → poll → display flow. Privacy Rules for DextDocument: Go to Data tab → Privacy → click 'DextDocument' (your receipt data type). Add a rule: 'This DextDocument's uploaded_by = Current User' → check View (all fields) for logged-in users. This ensures accountants can only see their own documents, and employees can only see their own submitted receipts. For multi-client firms: also add rules that allow accountants from a specific firm to see documents uploaded by any client under their firm. This requires a 'Firm' relationship field on both the User and DextDocument types — the Privacy Rule becomes 'This DextDocument's uploaded_by's firm = Current User's firm'. API key security: your Dext API key is stored as a Private header in the API Connector and never reaches the browser. However, if you store per-client API keys in the database, mark those fields as Private in Privacy Rules — no role should be able to view them through Bubble's Data API or the editor debug panel. End-to-end test: 1. Log into your Bubble app as a test user 2. Navigate to your expense submission page 3. Use the File Uploader to select a clear receipt image (JPEG, good lighting, text legible) 4. Click 'Upload Receipt' 5. Watch the Repeating Group for the new 'processing' document to appear 6. Wait for the auto-refresh to switch the status to 'processed' 7. Verify the extracted vendor, amount, date, and category are correct 8. Test with a second receipt to confirm the polling loop handles multiple concurrent uploads For Workload Unit (WU) awareness: each upload consumes WU for the API call, and each polling iteration consumes WU for the Backend Workflow run and the GET /documents API call. A single receipt with 10 polling attempts = approximately 11 WU operations. If you have 100 users uploading 5 receipts each per day = 5,500 WU operations daily from the Dext integration alone. Factor this into your Bubble plan's WU budget. RapidDev's team has helped accounting firms build automated receipt processing workflows in Bubble with Dext — if you need help with the polling architecture or the multi-client key management pattern, book a free scoping call at rapidevelopers.com/contact.

dext-privacy-and-e2e-test.json
1// Privacy Rules for DextDocument type:
2// Rule 1: 'This DextDocument's uploaded_by is Current User'
3// → View: all fields checked
4// → Purpose: employees/users see only their own receipts
5
6// Rule 2 (for accounting firms, optional):
7// 'This DextDocument's uploaded_by's firm is Current User's firm
8// AND Current User's role is Accountant'
9// → View: all fields checked
10// → Purpose: accountants see all documents from clients in their firm
11
12// WU budget estimate per 100 active users:
13// - 5 uploads/user/day × 100 users = 500 upload API calls/day
14// - 500 uploads × avg 8 polling attempts = 4,000 polling calls/day
15// - Total: ~4,500 WU operations/day from Dext integration
16// Monitor in Bubble Logs → Workflow logs tab
17
18// End-to-end verification checklist:
19// [ ] Upload a receipt → document_id appears in database
20// [ ] Status starts as 'processing'
21// [ ] Status updates to 'processed' within 90 seconds
22// [ ] vendor_name, total_amount, document_date, category populated
23// [ ] Privacy Rules: user B cannot see user A's documents
24// [ ] Timeout path tested (at 15 attempts): status = 'timeout'

Pro tip: Test the timeout path explicitly by temporarily setting your max_attempts to 2 in the polling workflow and uploading a receipt. Verify that after 2 attempts the DextDocument status becomes 'timeout' and your UI shows an appropriate error message. Then reset to 15 attempts. Never leave the timeout path untested — it is the fallback your users will eventually hit on a slow processing day.

Expected result: Privacy Rules prevent users from seeing each other's expense documents. End-to-end test confirms: receipt upload creates a DextDocument record, OCR completes within 90 seconds, extracted fields populate automatically, and the Review UI displays the data correctly. The timeout path shows an error message after 75 seconds if processing has not completed.

Common use cases

Employee Receipt Submission Portal

Let employees photograph and upload expense receipts directly in a Bubble app. After upload, Dext's OCR extracts the vendor, amount, date, and category automatically — no manual data entry. Employees review the extracted data, add any additional notes (project code, cost center), and submit for approval. Managers can see all pending expense claims in a Repeating Group filtered by their team.

Bubble Prompt

Build a Bubble expense submission portal where employees can upload a receipt photo, see the automatically extracted vendor and amount, add a cost center, and submit the expense for manager approval — all without typing the receipt details manually.

Copy this prompt to try it in Bubble

Accountant Document Processing Dashboard

Build an internal Bubble tool for an accounting firm to receive client documents, run them through Dext OCR, and categorize extracted data before pushing to QuickBooks or Xero. Each client has their own Dext API key stored in Bubble's database — the correct key is used based on which client the accountant is currently working with.

Bubble Prompt

Build a Bubble tool for an accounting firm where accountants can upload client receipts, see the Dext-extracted data (vendor, amount, VAT, date), assign to the correct ledger category, and mark as processed — supporting multiple clients with separate Dext accounts.

Copy this prompt to try it in Bubble

Automated Invoice Data Capture

Allow suppliers to upload invoices to a Bubble portal, where Dext's OCR extracts the invoice number, supplier name, line items, and total amount. Extracted data populates a Bubble Invoice record automatically. Accounts payable staff only need to approve the extracted data, not re-key it from paper invoices.

Bubble Prompt

Build a Bubble accounts payable portal where suppliers upload invoice PDFs, Dext extracts the invoice number, line items, and total, and the extracted data auto-populates an invoice record for AP approval.

Copy this prompt to try it in Bubble

Troubleshooting

API call returns 401 even after entering the correct API key in the Authorization header

Cause: Dext's API may use 'ApiKey {key}' as the Authorization header value, not the more common 'Bearer {key}'. Using the wrong prefix — even with a valid key — results in 401 Unauthorized. This is a documented gotcha specific to Dext.

Solution: Verify the exact Authorization header format in Dext's current API documentation at developers.dext.com. Try both formats: 'ApiKey YOUR_KEY_HERE' and 'Bearer YOUR_KEY_HERE' in your API Connector shared header. Make sure the Private checkbox is enabled on the header regardless of which format works. If switching formats does not resolve the 401, confirm your API key was copied fully without trailing whitespace.

API call returns 403 Forbidden immediately, even though the API key format appears correct

Cause: A 403 (Forbidden) response means authentication succeeded but your account is not authorized to use the API — this is a plan-level access restriction, not a credentials error. API access is not included in all Dext account tiers.

Solution: Contact Dext support (support@dext.com) and ask them to confirm whether your account plan includes API access. If not, request API access to be enabled, or ask which plan tier includes it. This is an account issue that no amount of configuration changes in Bubble will fix — the API key itself is valid, but the account is blocked from using the API endpoint.

The DextDocument status stays 'processing' indefinitely and never changes to 'processed'

Cause: Common causes: (1) the polling Backend Workflow is not running (Backend Workflows require a paid Bubble plan and must be enabled under Settings → API), (2) the polling loop has an error in its condition logic and is not rescheduling itself, (3) Dext's OCR queue is slow on this particular document (PDF files with many pages can take several minutes), or (4) the document upload was malformed and Dext is stuck on it.

Solution: Check Bubble's Workflow Logs (Logs tab → filter to Backend Workflows) to see if Dext_PollDocumentStatus is running. If it ran zero times after the upload, confirm the upload workflow correctly schedules the first polling call. If the workflow is running but the status response from Dext is always 'processing', check the Dext developer portal for the document's status — if it shows 'failed' in Dext but your Bubble workflow only handles 'processed'/'processing', add a 'failed' status branch to your polling workflow. Set your max_attempts appropriately (15 is recommended).

Backend Workflow for polling is not available in the Bubble editor

Cause: Backend Workflows (API Workflows) require a paid Bubble plan and must be explicitly enabled in the app settings. They do not appear on free plans.

Solution: Upgrade to a paid Bubble plan. Then go to Settings → API → check 'This app exposes a Workflow API'. After enabling this, refresh your editor and the Backend Workflows section will appear. The Dext integration's async polling is fundamentally incompatible with Bubble's free plan — this is a hard requirement, not a workaround.

'There was an issue setting up your call' when initializing the Poll Status API call

Cause: The Initialize Call for GET /documents/{document_id} requires a real, active document_id from a document that has already completed processing. You cannot initialize with a placeholder document_id — Dext will return 404, causing initialization to fail.

Solution: Complete the full upload flow first: upload a real receipt image using your 'Upload Document' call, wait for Dext to process it (check your Dext account dashboard to see when it shows as 'processed'), then use the resulting document_id as the parameter value when running the Initialize Call for Poll Status. Once initialized successfully with a processed document, Bubble captures the full response shape and you can proceed.

Best practices

  • Verify API access is enabled on your Dext account before writing any Bubble configuration — a 403 response from the first API call is almost always a plan-tier restriction, not a configuration error; confirm with Dext support before debugging.
  • Always store the Dext API key as a Private header in the API Connector — the Private checkbox keeps the key on Bubble's servers and never exposes it to browser network requests.
  • Set a maximum polling attempt count (15 attempts recommended) and build an explicit 'timeout' status path — document processing occasionally hangs, and without a max, your Backend Workflow scheduling queue can grow indefinitely.
  • For multi-client accounting firms, store one Dext API key per client in a Clients data type with Privacy Rules that prevent the key from being visible to non-admin users — never use a single shared API key that mixes documents from multiple clients into one Dext account.
  • Store the original receipt file URL in your DextDocument database record alongside the extracted fields — users often need to view the original image to verify OCR accuracy, and losing the file URL means you must re-upload.
  • Apply Bubble Privacy Rules to the DextDocument data type immediately — without Privacy Rules, any logged-in user can query all expense documents through Bubble's Data API, regardless of who uploaded them.
  • Monitor WU consumption in Bubble's Logs tab during testing with realistic document volumes — each polling iteration counts as a Backend Workflow execution; at scale, the polling loop can be the largest WU cost in your app.
  • Test the end-to-end flow with multiple receipt types (JPEG photos, PDFs, multi-page invoices) before going live — Dext's OCR accuracy varies by document quality and type; set user expectations appropriately and build an easy correction UI.

Alternatives

Frequently asked questions

Is Receipt Bank the same as Dext?

Yes — Receipt Bank rebranded to Dext in 2021. The product is the same OCR expense capture platform; only the brand name and URLs changed. The API is now at api.dext.com instead of any previous Receipt Bank endpoint. If you are following an older tutorial that references Receipt Bank's API, update all URLs to use the dext.com domain.

Can I build the Dext integration on Bubble's free plan?

No. The asynchronous OCR polling loop requires Backend Workflows (API Workflows), which are only available on paid Bubble plans. Without Backend Workflows, there is no way to implement the wait-and-retry pattern needed after receipt upload. Upgrade to a paid plan before building this integration.

How long does Dext's OCR take to process a receipt?

Typically 10–60 seconds for a clear JPEG photo of a single receipt. PDFs and multi-page invoices may take longer. The timing also depends on Dext's queue load at the time of upload. Build your polling loop to handle up to 75–90 seconds (15 attempts × 5 seconds) before displaying a timeout error. If processing routinely exceeds this, the user can check back later — the document will be ready in Dext's system even after your polling timeout.

Why does the Authorization header need 'ApiKey' as a prefix instead of 'Bearer'?

Dext's API uses a custom authorization scheme — 'ApiKey' — rather than the more common 'Bearer' scheme used by OAuth-based APIs. The exact format must match what Dext expects, character for character. Using 'Bearer' with a Dext API key returns 401 even if the key itself is valid. Always verify the current required format in Dext's official API documentation, as this can change between API versions.

Can my Bubble app handle receipts for multiple clients with separate Dext accounts?

Yes, but it requires per-client API key management in Bubble. Create a 'Clients' data type with an 'api_key' field (marked Private in Privacy Rules). When an accountant selects a client to work on, your upload and polling workflows use that client's API key by fetching it from the Clients record at runtime. Each Dext API key is scoped to one Dext account — mixing clients into a single Dext account means their documents are visible to each other in Dext's interface, which is a privacy concern for most accounting firms.

What happens if a receipt fails OCR processing?

Dext returns a 'failed' or 'error' status on the document when OCR cannot extract data — this can happen with very blurry images, handwritten receipts, or corrupted file uploads. Build your polling workflow to handle the 'failed' status explicitly: update the DextDocument status to 'failed' in Bubble's database and show the user a message like 'Processing failed — please upload a clearer image of the receipt.' Log the document_id so you can investigate failed documents in the Dext developer portal.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation
Matt Graham

Written by

Matt Graham · CEO & Founder, RapidDev

1,000+ client projects delivered. Columbia University & Harvard Business School alumnus, U.S. Navy veteran. About the author →

Integrations are where projects stall

We wire Bubble integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.