Request links
Ask one customer for documents, camera captures, answers and identity checks through a single link, and get everything back in one record.
A request link is a custom information request for one customer. You compose what you need, Speedmap gives you a link (or sends it by email or SMS), the customer answers everything on one branded, mobile-first page, and you read it all back in one record: files, answers, capture results and verification references.
Typical use: a customer you already onboarded, where you later need more evidence. "Upload your NIN slip." "A photo of a recent utility bill." "A selfie holding your ID." "Your current address." Or a real NIN or BVN check, run through the engine like any other verification.
Item types
Up to 15 items, answered in the order you give them. Each item has an optional label and instructions (plain text, shown to the customer) and a required flag (default true; optional items can be skipped).
| Type | What the customer does | What you get |
|---|---|---|
upload | Picks a file or takes a photo: JPG, PNG or PDF, up to 10 MB each. accept limits the types, multiple allows up to 5 files. | The file(s), encrypted at rest, downloadable through the API or the dashboard. Collected only: no OCR or matching. |
capture | A guided camera step from the capture SDK: document, selfie, selfie_with_id (selfie, then the document, face-matched) or liveness. document_types limits the documents accepted. | A capture session with one verification per step (billed as Document and Liveness). |
question | Answers in the format you set: text, date (YYYY-MM-DD), select (one of options) or yes_no. | The answer, sealed at rest and returned in clear on the request. |
verification | Types the inputs the product needs: nin (NIN plus a selfie), bvn (BVN, name, date of birth), account (account number and bank) or face (selfie). | A normal verification linked by reference_id, billed at the product's price. The outcome is never shown to the customer. |
An upload labelled "NIN slip" is just a file. A verification item with product: "nin" runs the real check.
What it costs
- Every completed request in live mode is charged the request fee (currently ₦50) to your wallet, as a ledger charge noted "Request link". The fee is held when the link is created, charged when the customer finishes, and released if the link expires or you cancel it. If the wallet cannot cover the hold, creation fails with
402 insufficient_balance. - Verifications and captures inside the request are charged at their normal price when they run, exactly like a direct API call.
- Sandbox requests are free, SMS is simulated, and checks answer with the usual test values.
Create a request
Body parameters
itemsarrayrequired1 to 15 items (see the table above).
subjectobjectname,email,phone,external_id. Sealed at rest; email and phone are returned masked. Required for delivery:emailto send by email,phone(Nigerian mobile or E.164) to send by SMS.messagestringShown to the customer above the items. Plain text, up to 1,000 characters.
deliverystring[]["email"],["sms"]or both. Empty (default): you send theurlyourself.expires_in_daysinteger1 to 30. Default 7.
reasonstringPurpose code for the checks inside the request. Default
financialProducts.brandobjectname,logo_url,color(6-digit hex) for the customer page. Default: your organization name.metadataobjectUp to 20 keys, returned on the request and in the webhook.
curl -X POST "https://api.speedmap.io/v1/requests" \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"type": "upload",
"label": "NIN slip",
"instructions": "A clear photo or scan of the slip.",
"accept": [
"jpg",
"png",
"pdf"
]
},
{
"type": "upload",
"label": "Utility bill",
"instructions": "Issued in the last 3 months.",
"accept": [
"pdf",
"jpg"
],
"required": false
},
{
"type": "capture",
"kind": "selfie_with_id"
},
{
"type": "question",
"format": "text",
"label": "Current residential address"
},
{
"type": "question",
"format": "select",
"label": "Employment status",
"options": [
"Employed",
"Self-employed",
"Student",
"Retired"
]
},
{
"type": "verification",
"product": "nin"
}
],
"subject": {
"name": "Clarke Griffin",
"email": "clarke@example.com",
"phone": "08031234567",
"external_id": "CUST-42"
},
"message": "To finish your loan application we need a few more things. It takes about five minutes.",
"delivery": [
"email",
"sms"
],
"expires_in_days": 7
}'{
"id": "req_7f3a1c9e2b4d6f80",
"object": "request",
"status": "pending",
"mode": "live",
"url": "https://speedmap.io/r/Qm9wZS1pcy1ub3QtYS1zdHJhdGVneS0yMDI2",
"subject": {
"name": "Clarke Griffin",
"email": "c*****@example.com",
"phone": "**********4567",
"external_id": "CUST-42"
},
"message": "To finish your loan application we need a few more things. It takes about five minutes.",
"items": [
{
"index": 0,
"type": "upload",
"label": "NIN slip",
"required": true,
"accept": [
"jpg",
"png",
"pdf"
],
"multiple": false,
"status": "pending",
"files": []
},
{
"index": 1,
"type": "upload",
"label": "Utility bill",
"required": false,
"accept": [
"pdf",
"jpg"
],
"multiple": false,
"status": "pending",
"files": []
},
{
"index": 2,
"type": "capture",
"label": "Selfie and ID document",
"kind": "selfie_with_id",
"required": true,
"status": "pending"
},
{
"index": 3,
"type": "question",
"label": "Current residential address",
"format": "text",
"required": true,
"status": "pending"
},
{
"index": 4,
"type": "question",
"label": "Employment status",
"format": "select",
"options": [
"Employed",
"Self-employed",
"Student",
"Retired"
],
"required": true,
"status": "pending"
},
{
"index": 5,
"type": "verification",
"label": "NIN check",
"product": "nin",
"required": true,
"status": "pending",
"reference_id": null
}
],
"delivery": {
"email": {
"requested_at": "2026-10-30T09:12:04.118Z",
"outbox_id": "eml_2c1f0a9b8d7e6f54",
"to": "c*****@example.com",
"status": "queued"
},
"sms": {
"requested_at": "2026-10-30T09:12:04.402Z",
"status": "sent",
"provider": "fintava_sms",
"to": "**********4567"
}
},
"fee_kobo": 5000,
"fee_status": "held",
"consent_at": null,
"expires_at": "2026-11-06T09:12:04.000Z",
"completed_at": null,
"created_at": "2026-10-30T09:12:04.000Z"
}The url is shown once
Speedmap stores a hash of the link, not the link. Copy url from the create response, or let Speedmap deliver it. Resend issues a new link (the old one stops working) and sends it again.
What the customer sees
The link opens speedmap.io/r/{token}: your name, your message, the list of items and a consent notice. The customer accepts the notice, then answers the items in order; progress is saved per item, so they can close the page and come back. Verification items collect the inputs on the page (the number, a selfie) and show only "received" or "try again", never the record. Expired, cancelled and completed links show a clear state.
Read the record
{
"id": "req_7f3a1c9e2b4d6f80",
"object": "request",
"status": "completed",
"mode": "live",
"subject": {
"name": "Clarke Griffin",
"email": "c*****@example.com",
"phone": "**********4567",
"external_id": "CUST-42"
},
"message": "To finish your loan application we need a few more things. It takes about five minutes.",
"items": [
{
"index": 0,
"type": "upload",
"label": "NIN slip",
"status": "done",
"files": [
{
"id": "rqf_9a8b7c6d5e4f3a21",
"filename": "nin-slip.jpg",
"mime": "image/jpeg",
"size_bytes": 418221,
"sha256": "3f2c…",
"purged": false
}
]
},
{
"index": 1,
"type": "upload",
"label": "Utility bill",
"status": "skipped",
"files": []
},
{
"index": 2,
"type": "capture",
"label": "Selfie and ID document",
"status": "done",
"capture_session_id": "cap_1d2e3f4a5b6c7d8e",
"result": {
"steps": {
"selfie": {
"reference_id": "spm_5e6f7a8b9c0d1e2f3a4b5c6d",
"status": "verified",
"match": null
},
"document": {
"reference_id": "spm_6f7a8b9c0d1e2f3a4b5c6d7e",
"status": "verified",
"match": true
}
}
}
},
{
"index": 3,
"type": "question",
"label": "Current residential address",
"status": "done",
"answer": "12 Adetokunbo Ademola Crescent, Wuse II, Abuja"
},
{
"index": 4,
"type": "question",
"label": "Employment status",
"status": "done",
"answer": "Employed"
},
{
"index": 5,
"type": "verification",
"label": "NIN check",
"status": "done",
"reference_id": "spm_3f9c1a7b2e4d6f8a0b1c2d3e",
"result": {
"status": "verified",
"match": true
},
"verification": {
"reference_id": "spm_3f9c1a7b2e4d6f8a0b1c2d3e",
"product": "nin",
"method": "in_person",
"status": "verified",
"match": true
}
}
],
"delivery": {
"email": {
"requested_at": "2026-10-30T09:12:04.118Z",
"outbox_id": "eml_2c1f0a9b8d7e6f54",
"to": "c*****@example.com",
"status": "queued"
},
"sms": {
"requested_at": "2026-10-30T09:12:04.402Z",
"status": "sent",
"provider": "fintava_sms",
"to": "**********4567"
}
},
"fee_kobo": 5000,
"fee_status": "charged",
"consent_at": "2026-10-30T13:58:40.221Z",
"expires_at": "2026-11-06T09:12:04.000Z",
"completed_at": "2026-10-30T14:03:11.004Z",
"created_at": "2026-10-30T09:12:04.000Z"
}Each item carries its status (pending, done, skipped) and, on the single-request read, its answer, files, verification (the assertion) or the capture result with one reference per step. Download a file with GET /v1/requests/{id}/files/{file_id}; every download is recorded in your audit log as a reveal. Files and sealed answers are purged under your retention policy; the record of what was asked stays.
Resend, cancel, list
resend takes an optional channels array (default: the channels used before) and returns the request with a fresh url. cancel closes the link and releases the fee hold. The list supports status, limit and before like every other list.
Templates
Save a list of items (and a message) you ask for often, then load it when you create a request.
curl -X POST "https://api.speedmap.io/v1/request-templates" \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Address proof",
"message": "Please send a recent utility bill and confirm your address.",
"items": [
{
"type": "upload",
"label": "Utility bill",
"accept": [
"pdf",
"jpg"
]
},
{
"type": "question",
"format": "text",
"label": "Current address"
}
]
}'Webhook
request.completed fires when the customer answers the last item. It is PII-free: item statuses, verification reference ids, file ids, your external_id and metadata. Read answers and files with GET /v1/requests/{id}. The dashboard user who created the request also gets an in-app notice.
{
"id": "evt_0c9d8e7f6a5b4c3d",
"type": "request.completed",
"mode": "live",
"created_at": "2026-10-30T14:03:11.090Z",
"data": {
"id": "req_7f3a1c9e2b4d6f80",
"object": "request",
"status": "completed",
"mode": "live",
"external_id": "CUST-42",
"fee_kobo": 5000,
"items": [
{
"index": 0,
"type": "upload",
"label": "NIN slip",
"status": "done",
"reference_id": null,
"capture_session_id": null,
"result": null,
"file_ids": [
"rqf_9a8b7c6d5e4f3a21"
]
},
{
"index": 1,
"type": "upload",
"label": "Utility bill",
"status": "skipped",
"reference_id": null,
"capture_session_id": null,
"result": null,
"file_ids": []
},
{
"index": 2,
"type": "capture",
"label": "Selfie and ID document",
"status": "done",
"reference_id": null,
"capture_session_id": "cap_1d2e3f4a5b6c7d8e",
"result": {
"steps": {
"selfie": {
"reference_id": "spm_5e6f7a8b9c0d1e2f3a4b5c6d",
"status": "verified",
"match": null
},
"document": {
"reference_id": "spm_6f7a8b9c0d1e2f3a4b5c6d7e",
"status": "verified",
"match": true
}
}
}
},
{
"index": 3,
"type": "question",
"label": "Current residential address",
"status": "done",
"reference_id": null,
"capture_session_id": null,
"result": null
},
{
"index": 4,
"type": "question",
"label": "Employment status",
"status": "done",
"reference_id": null,
"capture_session_id": null,
"result": null
},
{
"index": 5,
"type": "verification",
"label": "NIN check",
"status": "done",
"reference_id": "spm_3f9c1a7b2e4d6f8a0b1c2d3e",
"capture_session_id": null,
"result": {
"status": "verified",
"match": true
}
}
],
"consent_at": "2026-10-30T13:58:40.221Z",
"completed_at": "2026-10-30T14:03:11.004Z",
"created_at": "2026-10-30T09:12:04.000Z"
}
}Key scopes
A scoped key needs the scope of every check or capture inside the request (nin, bvn, account, face, document, liveness). A request that only collects files and answers works with any key.
Dashboard
Verification links → Requests has the same builder: add, remove and reorder items, write the message, pick expiry and delivery, save or load a template. Each request has a page with every answer, file preview and download (audited), verification result, delivery status with resend, and cancel.
Questions? Email developers@speedmap.io. This page is also available as Markdown.