Using Veryfi Lens Instant App or App Clip
You can launch our Android Instant App or iOS App Clip to process a document directly from your WhatsApp bot.
Steps:
Create a Call-to-Action (CTA) component in your WhatsApp bot.
Refer to the WhatsApp documentation:
Set the action URL based on the user's device:
iOS:
https://appclip.apple.com/id?p=com.veryfi.Lens-Demo.Clip&${urlParams}
Android:
https://whatsapp-bot.veryfi.com/instantapp/?${urlParams}
Build the URL parameters with the desired Lens configuration:
const urlParams = new URLSearchParams({
documentType,
showDocumentTypes,
autoDocDetectionAndCropIsOn,
blurDetectionIsOn,
locationServicesIsOn,
webhook,
uploadWithoutProcessingIsOn,
tags,
externalId,
campaignId,
username: encodeURIComponent(username),
clientId: encodeURIComponent(clientId),
key: encryptedApiKey
});
Parameters
Parameter | Description |
---|---|
documentType | Type of document to capture (e.g., "receipt", "invoice"). |
showDocumentTypes | Show document type selection screen (true / false). |
autoDocDetectionAndCropIsOn | Enable automatic document detection and cropping (true / false). |
blurDetectionIsOn | Enable blur detection before capturing (true / false). |
locationServicesIsOn | Enable location tracking during capture (true / false). |
dataExtractionEngine | Set to "api" to use the Veryfi Data Extraction API. |
externalId | Add a unique reference identifier for a scan, allowing you to easily map the document back to your system |
campaignId | Link the document to an existing campaign on your system |
tags | Optional list of custom tags for Veryfi to use in tagging submitted documents |
uploadWithoutProcessingIsOn | If dataExtractionEngine is none it will upload the package to our servers but will defer the processing to the webhook, default: true |
webhook | A url that will be used instead of the one owned by Veryfi to send the package data |
username | Veryfi username (URL-encoded). |
clientId | Veryfi Client ID (URL-encoded). |
key | Encrypted Veryfi API key. |
🔐 Encrypting the apiKey Parameter
To securely send your Veryfi API key in the Lens Instant App or App Clip URL, you must encrypt it using our public key.
Note: Only the Instant App or App Clip (holding the corresponding private key) can decrypt it.
1. Download the Public Key
Download the Lens Instant App / App Clip public key here:
2. Encrypt the API Key in Your Backend
Use RSA-OAEP with SHA-256 to encrypt the API key. This example shows how to do it in Node.js:
// crypto/encryptKey.js
import crypto from "crypto";
import fs from "fs";
// Convert buffer to URL-safe Base64 (base64url)
const b64u = (buf) =>
Buffer.from(buf).toString("base64")
.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
export function encryptApiKeyForApp(publicKeyPem, apiKeyPlaintext) {
const ciphertext = crypto.publicEncrypt(
{
key: publicKeyPem,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: "sha256",
},
Buffer.from(apiKeyPlaintext, "utf8")
);
return b64u(ciphertext); // URL-safe string
}
// Example usage:
const publicKeyPem = fs.readFileSync("./veryfi_lens_public.pem", "utf8");
const encryptedKey = encryptApiKeyForApp(publicKeyPem, process.env.VERYFI_API_KEY);
console.log("Encrypted key:", encryptedKey);
4. How it Looks in WhatsApp
Below is an example of how this Call-to-Action (CTA) button with the encrypted key parameter will appear inside a WhatsApp conversation:
📸 Screenshot Example

5. Payload sent to the webhook
5.1 If uploadWithoutProcessingIsOn = true
and dataExtractionEngine = none
, then the payload will contain the data to find the document location so that you can process it via API:
{
"data": {
"bucket": "veryfi-lens-uploads",
"document_type": "receipt",
"external_id": "your-external-id",
"img_original_path": "path/to/original/image.jpg",
"img_stitched_pdf_path": "path/to/stitched.pdf",
"img_thumbnail_path": "path/to/thumbnail.jpg",
"package_path": "path/to/package.zip",
"upload_time_s": 3,
"img_paths": ["path/to/image1.jpg", "path/to/image2.jpg"]
},
"device_id": "ed259234-5610-33b7-ab5b-4b2bc3f2cac2",
"document_type": "receipt",
"package_id": "package-456",
"status": "success"
}
5.2 If dataExtractionEngine = api
, then the full processed response will be sent:
{
"package_id": "edc8653e4c2b4ef1",
"data": {"account_number": "", "bill_to": {"address": "", "name": ""}, "card_number": "", "category": "Meals & Entertainment", "created_date": "2021-01-14 05: 19: 51", "currency_code": "USD", "date": "2021-01-14 05: 19: 51", "delivery_date": "", "discount": 0, "due_date": "", "external_id": "", "id": 31428417, "img_file_name": "xxxxxxxxx.png", "img_thumbnail_url": "https: \/\/cdn.veryfi.com\/partner-receipts\/xxxxxxxxx_t.png", "img_url": "https: \/\/cdn.veryfi.com\/partner-receipts\/xxxxxxxxx.png", "incoterms": "", "insurance": "", "invoice_number": "", "line_items": [], "notes": "", "ocr_text": "starbucks 23.4", "order_date": "", "payment": {"card_number": "", "display_name": "No Payment,", "type": "no_payment,"}, "phone_number": "", "purchase_order_number": "", "reference_number": "VBDEC-0000", "service_end_date": "", "service_start_date": "", "ship_date": "", "shipping": 0, "subtotal": 23.4, "tags": [], "tax": 0, "tip": 0, "total": 23.4, "total_weight": "", "vendor": {"abn_number": "", "address": "", "fax_number": "", "logo": "https: \/\/cdn.veryfi.com\/logos\/us\/910419611.png", "name": "Starbucks", "phone_number": "", "raw_name": "Starbucks", "type": "", "vat_number": ""}}
}
Important Notes
- Do not send the raw API key in the URL.
- The encryption must be done on your backend, never in frontend code.
- The encrypted value is already URL-safe (base64url); avoid double-encoding.