Overview
Verification is two calls. verify-identity matches the details the customer gives and sends a six-digit code; verify-otp checks the code and returns a session_token. Every account endpoint then requires that session. The same contract applies whether the endpoints are yours (Account Connect) or provided by Silux Chat on top of a connector.
| Account Connect (your endpoints) | Connector (our endpoints on your vendor) | |
|---|---|---|
| Who matches the customer | Your system | Silux Chat, by looking the customer up in your vendor system (or, where the vendor has no customer search, on their own orders or bookings) |
| Who sends the code | Your system, to the registered mobile | Silux Chat, to the mobile or email the vendor holds |
| Code and session lifetimes | You decide (recommended 10 and 30 minutes) | 10 minutes and 30 minutes |
| Wrong-code limit | You enforce (recommended 5) | 5, enforced by the platform |
| Base address | Yours, e.g. https://api.yourcompany.com/silux | https://www.siluxchat.com/api/connect/{connection_id} |
The full sequence
┌──────────────┐ name + postcode/email/mobile ┌────────────────────┐
│ UNVERIFIED │ ───────────────────────────────►│ verify-identity │
└──────────────┘ └─────────┬──────────┘
▲ success:false (no detail on WHY) │ success:true
│◄──────────────────────────────────────────────────┤ otp_token (10 min)
│ ▼
│ ┌────────────────────┐
│ 5 wrong codes / token expired │ CODE SENT │
│◄─────────────────────────────────────── │ verify-otp │◄─┐ wrong code
│ └─────────┬──────────┘ │ (tries < 5)
│ │ correct ────┘
│ ▼
│ ┌────────────────────┐
│ session expires (30 min) → 401 │ VERIFIED │
└──────────────────────────────────────── │ session_token │
└────────────────────┘
account-summary · orders · invoices · bookings · subscriptions · tickets- 1The customer asks something personal. The bot asks for their full name and one more detail.
- 2The bot sends
verify-identity. On a match, a code goes to contact details already on the account and anotp_tokencomes back. - 3The bot tells the customer where the code went (“a text to the mobile ending 123”) and asks for it.
- 4The bot sends
verify-otpwith the token and the code. On success it receives asession_token. - 5Account tools are unlocked for that conversation until the session expires.
Step 1: verify-identity
{base}/verify-identityX-API-KeyMatches the customer and sends a one-time code.
| Field | Type | Notes |
|---|---|---|
| full_name | string | Always sent. Compare case- and space-insensitively. |
| postcode | string | May be empty. Compare without spaces: SW1A1AA equals SW1A 1AA. |
| string | May be empty. | |
| mobile_number | string | May be empty. Accept 07… and +44 7… forms. |
curl -s -X POST "https://www.siluxchat.com/api/account-connect-demo/v1/verify-identity" \
-H "X-API-Key: demo-account-connect-key" \
-H "Content-Type: application/json" \
-d '{"full_name":"Test Customer","postcode":"TE5 7ST"}'{
"success": true,
"otp_token": "eyJrIjoib3RwIiwiYyI6IkMxMDAxIiwiZXhwIjoxNzkwNDE2NTg2LjI4NDIyNDN9.443c18a766f3c03f371e3da90a269fdf",
"message": "Code sent to mobile ending 000"
}{
"success": false,
"message": "We could not match those details to an account."
}A “no” is HTTP 200 with "success": false. Reserve 401 for a missing or wrong API key. The message is shown to the customer in substance, so keep it short and neutral.
Never say which detail was wrong
“That postcode doesn’t match” tells an attacker the name was right. Always return the same message for every kind of mismatch, and for accounts that do not exist.Matching rules
Account Connect
Your system decides, but the specification is: the full name must match, and at least one of postcode, email or mobile must match the same account. Normalise before comparing — lower-case, remove spaces.
Connectors
- The customer is looked up in your vendor system by email, and otherwise by mobile. A postcode alone cannot find an account, so on a connector the bot asks for an email address or mobile number.
- The surname (last word of the name) must match the record exactly, and the first name must either match or start with the same letter — so “Jan Smith” or “Janey Smith” match Jane Smith. Single-letter words are ignored, so a bare initial (“J Smith”) is not enough.
- Then one more detail must agree with the same record: postcode, email or mobile.
- Mobile numbers are compared on their last 10 digits, so
07700900123and+447700900123are the same number. - If the vendor cannot be reached or refuses the credentials, the reply is
{"success": false, "system_error": true, "message": "We can't check accounts right now — our team has been told."}. The bot never tells a customer “no account found” when the truth is that it could not look.
| Customer says | Record holds | Result |
|---|---|---|
| Jane Smith, jane@example.com | Jane Smith, jane@example.com | Match |
| Janey Smith, +44 7700 900123 | Jane Smith, 07700900123 | Match (same first letter + same mobile) |
| J Smith, jane@example.com | Jane Smith, jane@example.com | No match (a bare initial is ignored) |
| Jane Smyth, jane@example.com | Jane Smith, jane@example.com | No match (surname) |
| Jane Smith, SW1A 1AA only | Jane Smith, SW1A 1AA | Connector: cannot look up without email or mobile. Account Connect: match. |
Connectors with no customer search
Some vendors (Cal.com, Google Calendar, Etsy, eBay, AfterShip, ShipStation, Printful, Workiz) have no way to search customers, but their bookings or orders name the customer. For these, the customer’s own records are the proof:
- The bot needs the full name and the email address the customer used; a mobile number is not accepted here. Without a valid email the reply is
{"success": false, "needs": ["full_name", "email"], …}. - Their orders or bookings are looked up by that email. A record must name exactly that email and a name that passes the same surname-and-first-name rule above.
- The code is then emailed to that address — never texted, and never sent to a number typed in the chat.
- Once verified, only records that name the customer’s email are shown; a record that does not say whose it is, is not shown.
- A wrong name and a wrong email get the same reply, so the answer never reveals which detail was wrong.
Connectors that hold neither (carriers, Trello, Asana, Twilio and similar) cannot verify customers. verify-identity on them replies {"success": false, "not_supported": true, "message": "<Name> can't be used to check who you are — …"}. Carriers still answer parcel tracking by tracking number without verification — see Orders, delivery tracking & returns.
Where the code is sent
The code always goes to contact details already held on the account. The chat never chooses the destination, so knowing someone’s name and postcode is not enough to read their code.
| Route | Destination | Customer-facing message |
|---|---|---|
| Account Connect | Your system texts the mobile registered on the account. | Code sent to mobile ending 123 |
| Connector, business has SMS enabled | A text to the mobile the vendor holds. | Code sent by a text to the mobile ending 123 |
| Connector, no SMS or no mobile | An email to the address the vendor holds. | Code sent by an email to j***@example.com |
| Connector, no mobile or email on file | Nothing is sent. | We found the account but have no mobile or email on it to send a code to — please contact us directly. |
| Connector verifying from orders/bookings | An email to the address on those records (the one the customer gave). | Code sent by an email to j***@example.com |
<Your business name> verification code: 482913. It expires in 10 minutes. Never share it.Mask what you reveal
Only ever reveal the last three digits of a mobile or the first letter of an email address. That is enough for a genuine customer to recognise, and useless to anyone else.Step 2: verify-otp
{base}/verify-otpX-API-KeyBody: {"otp_token": "…", "otp_code": "482913"}. Strip spaces from the code before comparing.
# export OTP=<otp_token from verify-identity>
: "${OTP:?export OTP first}"
curl -s -X POST "https://www.siluxchat.com/api/account-connect-demo/v1/verify-otp" \
-H "X-API-Key: demo-account-connect-key" \
-H "Content-Type: application/json" \
-d "{\"otp_token\":\"$OTP\",\"otp_code\":\"123456\"}"{
"success": true,
"session_token": "eyJrIjoic2Vzc2lvbiIsImMiOiJDMTAwMiIsImV4cCI6MTc5MDQxODAxMC45MTg4OTY3fQ.9c2f16ac077d2df711c89a5bc412537c"
}| Situation | Status | message |
|---|---|---|
| Wrong code | 200 | That code is not correct. |
| Token unknown or older than 10 minutes | 200 | That code has expired — please ask for a new one. |
| Fifth wrong code (connectors; recommended for yours) | 200 | Too many wrong codes — please ask for a new one. |
| Missing or wrong API key | 401 | Missing or wrong X-API-Key |
Time and attempt limits
| Limit | Value | What happens at the limit |
|---|---|---|
| Code lifetime | 10 minutes | verify-otp replies “That code has expired”; the bot offers to send a new code. |
| Wrong codes per otp_token | 5 | The token is destroyed; the customer must start again with a fresh code. |
| Session lifetime | 30 minutes | Account endpoints return 401 “Session expired — please verify again.” and the bot re-verifies. |
| Codes sent per conversation | Capped by the platform | Further requests are routed to your team instead of sending more texts. |
A used code is destroyed on success, so the same code can never open a second session. Store only a hash of each code on your side, as the reference implementations do.
Using the session
Send the session_token in the JSON body of every account call. It identifies the verified customer; the bot never sends a customer ID of its own choosing, so it cannot ask for anyone else’s data.
# export SESSION=<session_token from verify-otp>
: "${SESSION:?export SESSION first}"
curl -s -X POST "https://www.siluxchat.com/api/account-connect-demo/v1/account-summary" \
-H "X-API-Key: demo-account-connect-key" \
-H "Content-Type: application/json" \
-d "{\"session_token\":\"$SESSION\"}"{"detail": {"success": false, "message": "Session expired — please verify again."}}Continue with Account lookups.
The test customer
So the dashboard can test the chain without texting anyone, every implementation recognises one fictional customer:
| full_name | postcode | mobile | code | |
|---|---|---|---|---|
| Test Customer | TE5 7ST | test@example.com | 07700900000 | 123456 — never sent |
- Account Connect: your code must accept the test customer, issue an
otp_tokenwithout sending anything, accept123456and return a little sample data. - Connectors: Silux Chat intercepts the test customer, proves the credentials with a real read-only call to your vendor using a made-up customer, and replies
"Test customer — no code is sent; use 123456". Account calls in a test session read no customer data and return"test": true.
Why this is safe
- Possession, not knowledge. Names, postcodes and emails leak; the code proves the person controls the phone or inbox on the account.
- Enforced in code. The bot’s account tools will not run without a session, whatever it is told in the chat.
- No enumeration. Identical messages for every mismatch, plus attempt limits, stop guessing.
- Short-lived. Ten-minute codes and thirty-minute sessions limit the value of anything intercepted.
- Honest failures. An unreachable system produces “can’t check right now”, never a false “no account”.
More in Security & data protection.
Get help
If genuine customers are being rejected, or codes are not arriving, email support@siluxcall.co.uk with the time of the attempt and your connection name — never the customer’s code.
Need help with your integration?
Our integration team can review your endpoints, help you choose the right connector and check a test run with you. Tell us which system you use and what you would like the bot to answer.