Integrate website signup
Create the account, bot and subscription by API and sign the customer into live number preparation.
Developer guide for the commercial website — DEV delivery, 21 September 2026.
After completing the form and authorising payments, the customer should arrive signed into BeAI, see their assistant being prepared, then find its phone number and Edit my bot. This flow is for new customers directly under Beone, excluding resellers. Existing BeAI organisations use the separate enrollment operation below.
Responsibilities and setup
The website displays public plans, verifies the customer's email ownership, collects company/account/billing details and acceptance of the terms, and obtains a Mollie mandate on the Beone account. BeAI creates the organisation, its administrator, a preset bot and the subscription, collects the first monthly payment, prepares the included number and processes the invoice.
Do not collect the first subscription month or create a Mollie subscription on the website. The website obtains authorisation; BeAI owns subscription payments and their schedule. Do not separately create the organisation, user, bot or number order.
Beone must configure enabled public plans with a neutral active bot template, authorised default model rates for future customers, Mollie test, isolated Odoo billing, the test email recipient, workers and the public payment webhook. Use a dedicated Beone-root organisation administrator and its API key. Platform administrator privileges are unnecessary and would expose private plans.
Server environment:
BEAI_BASE_URL=https://ai-dev.beone.be
BEAI_API_KEY=<dedicated_account_API_key>
MOLLIE_API_KEY=<same_Beone_account_test_key>
WEBSITE_BASE_URL=https://<test-website>
Send Authorization: Bearer <BEAI_API_KEY>, Accept: application/json and Content-Type: application/json. Keep both API keys on your server. Browser requests go through your backend; BeAI CORS access is unnecessary. Test payments and invoices must stay isolated. Phone numbers still use real carrier infrastructure, so coordinate number reservations with Beone.
Customer journey
- Read
GET /api/v1/subscription-planson your backend. Display onlyenabled: trueandpublic: trueplans. - Collect the form, verify the customer's email and record acceptance of the displayed plan revision and terms.
- Create or recover this signup's Mollie customer and authorise a recurring mandate.
- Re-read Mollie and wait for a valid mandate. A browser return is not payment confirmation.
- Freeze a durable idempotency key and exact signup payload; call
POST /api/v1/website-signups. - Save the returned identifiers, then call
POST /api/v1/website-signups/{id}/handoff. - Redirect the customer's browser to the returned URL, including its fragment.
- BeAI signs in the newly created administrator and displays live account/payment/number/telephony progress.
- Once ready, the page shows the callable number, Edit my bot, and access to the unified billing page.
Do not wait for the number on the website before redirecting. Payment and number preparation continue when the browser closes.
Catalogue and Mollie authorisation
Plan responses expose id, code, name, revision, enabled, public, monthly_eur, included_minutes, overage_eur_per_minute, max_bots, template_id, currency: EUR and tax_mode: HTVA. Use returned identifiers and prices; initial plans are €70/200 minutes/1 bot, €140/400 minutes/2 bots and €210/600 minutes/5 bots, excluding VAT. Do not create the template bot yourself. Send plan_revision to reject changed prices with 409 before creation or charging.
Mollie normally establishes a mandate through a customer and a payment with sequenceType: first and customerId. Use the supported methods configured on the shared Beone account and re-read the resulting mandate. A zero-value authorisation depends on the payment method; do not assume every method supports it. If authorisation requires a small charge, agree its treatment with Beone: it is not automatically deducted from the BeAI monthly payment. See Mollie recurring payments, create payment and get mandate.
Send only customer_id, mandate_id, and optionally reported status and expires_at. BeAI verifies the mandate itself; verified data takes precedence. Some methods have no expiration. Never send card numbers, CVCs or Mollie API keys to the signup API.
The authorisation's redirectUrl returns the browser to your website; its webhookUrl notifies your backend, which re-reads Mollie. BeAI uses its own webhook for the first subscription payment and renewals. The BeAI handoff URL is a third, separate URL for initial login. There is no outbound “bot ready” webhook to your website in this delivery; use status polling.
Complete signup request
POST /api/v1/website-signups
Idempotency-Key: signup-<stable-UUID-for-this-signup>
{
"plan_id": 1,
"plan_revision": 1,
"organisation": {
"name": "Example Workshop",
"billing": {
"name": "Example Workshop SRL",
"email": "billing@example.be",
"address_line_1": "Example Street 10",
"address_line_2": "",
"postal_code": "1000",
"city": "Brussels",
"country_code": "BE",
"vat_number": ""
}
},
"user": {
"email": "customer@example.be",
"password": "<customer-chosen-password>",
"display_name": "Camille Example"
},
"bot": {
"company_description": "Bicycle repairs: tyres, brakes and transmissions. Quotes are provided after inspection at the workshop.",
"opening_hours": "Monday to Friday, 9 am to 6 pm. Closed on weekends.",
"website": "https://example.be"
},
"payment_method": {
"customer_id": "cst_example",
"mandate_id": "mdt_example",
"status": "valid",
"expires_at": null
}
}
All identifiers and addresses in this example are fictitious. Billing name, valid email, street, postal code, city and two-letter country code are required; address line 2 and VAT number are optional. The login email must be unique; the password must be at least ten characters and is hashed by BeAI. Never log it. The optional display name defaults to the company name.
The optional bot object customises the template. Defaults generate a French greeting identifying the bot as the company's AI assistant, concise company-based answers and instructions not to invent information or promise unconfigured actions. Recording and auto-improvement are enabled. Template transfer/email destinations, tags and external actions are not inherited.
Supported fields: name (120 characters), company_description (12,000), opening_hours (2,000), website (valid HTTP/HTTPS URL, 2,048), greeting_message, extra_infos (12,000 each), temperament (255), default_lang, voice, ai_model. Prefer the Beone-approved default language/voice/model. An unauthorised model is rejected. Combined knowledge must not exceed 65,535 bytes. The website URL is stored as knowledge; signup does not crawl the website. Supply the actual useful facts in the description.
Roles, organisation hierarchy and managed SIP settings are fixed by BeAI. Unknown fields are rejected.
Creation response and first payment
An accepted request returns 202, wrapped in data, with id, organisation_id, user_id, bot_id, legacy status, number, number_reservation_id, error, the full subscription, and onboarding. Save the identifiers immediately.
202 is not proof that the payment has completed or the bot is ready. BeAI creates the initial payment after mandate verification. Confirmed payment starts the contract and minute period, triggers the included number reservation and queues invoicing. The number has no additional customer rental charge within the plan. Invoice processing is asynchronous; an Odoo failure must never trigger another payment and does not block otherwise ready telephony.
Do not create another signup or call retry-payment automatically for pending or uncertain payments.
Initial login handoff
POST /api/v1/website-signups/{signup_id}/handoff
No business payload is required; {} is accepted. HTTP 200 returns:
{
"data": {
"url": "https://ai-dev.beone.be/welcome/0123456789abcdef0123456789abcdef/connect#ticket=<one-time-secret>",
"expires_at": "2026-09-21T15:10:00+00:00",
"single_use": true
}
}
Verify the URL's origin against your configured BeAI origin, then return it only to the authenticated website session owning this signup, with Cache-Control: no-store. In the browser, window.location.assign(result.redirect_url) opens it. Preserve the fragment. Do not pass it through analytics, link tracking, marketing email, support logs or persistent browser storage.
Links expire after ten minutes and are single-use. Issuing another link invalidates the previous one without creating resources or charging. Only the signup creator account or a platform administrator may issue a link, within 24 hours of signup creation. Another key belonging to the same account retains that permission; a different account does not.
The fragment is removed from browser history and exchanged using a CSRF-protected same-origin POST. A GET alone does not authenticate. BeAI replaces any prior session with the new customer administrator's session and clears the previous organisation context. Locked users, users moved out of the organisation or stripped of administrator rights, and effectively ended contracts cannot use the link.
After expiry or the issuance window, use the ordinary email/password login, including Forgot password when needed. onboarding.links.self reopens the welcome page without generating a login secret. There is no arbitrary return_url or callback_url parameter. Never expose an unauthenticated website endpoint issuing links for caller-supplied signup IDs.
Live status and customer actions
The Beone backend can read full signup status using GET /api/v1/website-signups/{id}. The customer-oriented endpoint is GET /api/v1/website-signups/{id}/onboarding, shared with the GUI and restricted to authorised organisation administrators and Beone.
Its response includes names/identifiers, status, title, message, ready, number, progress, payment, invoices, links, poll_after_seconds and checked_at.
| Status | Meaning |
|---|---|
awaiting_payment |
Waiting for the first payment; do not charge again |
payment_failed |
Payment failed; open billing to update the method and explicitly regularise |
preparing_number |
Payment confirmed; number assignment/routing in progress |
preparing_telephony |
Number assigned; checking telephony availability |
needs_attention |
Beone must investigate; preserve the signup and payment |
ready |
Payment confirmed, active routed number attached to this bot and telephony available |
suspended |
Settle outstanding charges to resume service |
ended |
Contract ended; history and invoices remain |
Use onboarding.status for new integrations; legacy signup status is less detailed. Only promise the bot can receive calls when ready === true, not just when a number exists. The four progress stages measure completed steps, not a time estimate.
Respect poll_after_seconds: five seconds while preparing, thirty when ready, null to stop. Back off after network errors and pause hidden tabs. The BeAI welcome page already handles this. links.edit_bot opens the editor and links.billing opens unified billing. Invoices remain independent; wait for pdf_available before calling GET /api/v1/organisations/{id}/subscription/invoices/{invoice_id}/pdf, URL-encoding the invoice ID.
Durable retries and error handling
Persist your signup ID, verified owner, stable idempotency key, accepted plan/revision/terms, Mollie references and BeAI identifiers. Lock your website signup so double clicks and duplicate authorisation webhooks converge on one operation. Keys must contain 8–100 letters, digits, periods, underscores, colons or hyphens.
If a creation response is lost, retry with the same account, same key and exact same payload. BeAI stores a durable fingerprint and returns 409 if the payload differs. Do not generate a new key for each retry. Once the BeAI signup ID is known, use GET to monitor it.
The payload contains a password: if asynchronous retry requires temporary retention, use restricted encrypted storage with a short lifetime and erase it after saving the BeAI ID. Never store the full payload as plaintext in logs, queues or observability systems. Status and handoff operations do not need the password.
Mollie's idempotency cache lasts one hour; use its keys for your authorisation operations but retain your own durable records. See Mollie idempotency.
| Response | Handling |
|---|---|
| 401/403 | Fix credentials or permissions, not the customer's card |
| 404 | Check identifiers, visibility and environment |
| 409 changed plan | Reload terms and obtain new acceptance before creation |
| 409 existing user/customer | Recover the existing account/signup; do not alter email or make duplicate customers to bypass it |
| 409 reused key with changed payload | Recover the original request before any new attempt |
| 409 handoff | Initial login unavailable; use ordinary login |
| 422 | Correct invalid fields, mandate or model after reading the detail |
| 503 Mollie verification | Temporary outage, not an invalid mandate |
| Timeout, 5xx or unreadable creation response | Unknown outcome: replay the original key and body |
| 202 with failed payment | Signup exists; open billing for explicit regularisation |
Long preparation or needs_attention |
Show progress/support and give identifiers to Beone; do not reorder a number |
Problem responses normally include detail; infrastructure failures may not return JSON. Never branch on the exact translated error text.
A deliberate mandate replacement can use POST /api/v1/organisations/{id}/payment-method/import under Beone's permissions. Explicit regularisation uses POST /api/v1/organisations/{id}/subscription/retry-payment with {"charge_id":"..."} and a new key for that regularisation action. Pending/uncertain payments cannot be retried. Neither action belongs in an automatic retry loop.
Commercial terms and existing customers
Before acceptance, display the chosen price excluding VAT, applicable tax treatment, minutes, overage and bot quota; shared minutes without rollover; the first indivisible AI minute followed by per-second counting; separate prepaid charges for overages and telephone branches/transfers/SMS/text; optional automatic recharge; twelve-month commitment billed monthly; cancellation during month one at its end without a pro-rata refund (not a free month); committed payments thereafter; one-calendar-month notice after commitment; cancellation withdrawal before effective termination; paid pro-rata upgrades without extending commitment; and number preparation after payment.
An existing BeAI organisation should use Subscription and billing, or authorised POST /api/v1/organisations/{id}/subscription with Idempotency-Key and {"plan_id":1,"plan_revision":1,"confirmed":true}. This preserves users, bots and credit; it does not create another bot or number. The website handoff cannot log into arbitrary existing accounts.
Acceptance checklist and GUI/API parity
Validate public-plan filtering, verified email and consent, shared Mollie test account, one signup/payment/invoice despite retries, company-specific preset, invalid/unavailable mandates, no premature number order, isolated invoice/email delivery, invoice recovery without recharging, included number and a real test call, correct one-time login/expiry/tenant scope, mobile welcome progress and editor CTA, recoverable network/provider errors, and absence of secrets in logs.
These are acceptance criteria, not a claim that the external website or a real call has already passed testing. Technical readiness does not replace a real call test.
The BeAI administrator signup assistant uses the same services and offers company details, welcome-page access and initial-link creation under identical permissions. /welcome/{id}/connect and /session are browser authentication transports; integrations call the public handoff API instead. Profile → API documentation exposes WebsiteSignupWrite, WebsiteSignup, WebsiteHandoff and WebsiteOnboarding with the operations visible to the current account. See Subscription and billing for ongoing management.
16. OVH website test checkout
The commercial website now uses a single French checkout for plan selection, email verification, company and assistant details, and a zero-value Mollie card authorisation. BeAI creates and collects the first subscription payment and provides the one-time login link. The test deployment only accepts the authorised test email and uses Mollie test with BeAI DEV. Interrupted checkouts can be resumed with the same email and a new code. An uncertain Mollie response is retained for reconciliation rather than creating a new command after the idempotency window.
External hosting uses https://ai-dev-public.beone.be. BeAI’s operator may configure the handoff origin through BEAI_WEBSITE_PUBLIC_URL; the browser cannot select it. GUI and API use the same service and preserve the existing expiry and permissions. The website’s internal form endpoints are transport endpoints, not additional BeAI business APIs.
Website operator access
The Beone root organisation administrator receives direct access only to each customer it successfully creates, consistently in the GUI and API. This does not grant access to unrelated customers or private plans. Failed validation rolls back the customer and access relationship before any payment.