Run a full verification cycle
Send and verify a free V1.2 test code from an empty terminal. Quickstart uses a fake Test Pair number and code returned by the server, so no real message goes out.
Quickstart turns dev mode on
Quickstart changes your account. It activates a Quickstart pipeline, turns on dev mode for it for one hour, and saves an API key when none is available. While dev mode is on, that pipeline skips its rate limits and circuit breaker. That is why quickstart needs --yes. Preview it first with --dry-run.
Log in with Full access.
akedly loginChoose Full access on the approval page. Quickstart refuses a Read-only login.
Check your setup.
akedly doctorIt checks your login, the server, your pipelines, your balance and WhatsApp, and sends nothing.
Preview the steps.
akedly quickstart --dry-runLists the steps quickstart would take and makes no requests.
Run it.
akedly quickstart --yesWithout
--yes, quickstart stops withCONFIRMATION_REQUIRED(exit 65) and changes nothing.
Next: the quickstart and doctor reference.
Connect WhatsApp
Connecting your own WhatsApp Business Account goes through Meta's sign-up in the dashboard. The CLI gives you the link and waits for the result.
Get the link and wait.
akedly whatsapp connect --waitThe CLI prints the dashboard link for your region and does not open a browser. It writes a
handoffevent to stderr in JSON mode (progress events).The link is on the dashboard of the deployment you are logged in to:
- Egypt:
https://app.akedly.io/admin/whatsapp-connect - KSA (
--ksa):https://ksa.app.akedly.io/admin/whatsapp-connect
- Egypt:
Finish the sign-up in the dashboard.
View in dashboardChannels → Setup → WhatsApp Setup(opens in a new tab)Connect your WhatsApp Business Account through Meta. This card opens the Egypt dashboard; for KSA, use the link the CLI printed.
Meanwhile the CLI checks
akedly whatsapp statusevery 10 seconds for up to 10 minutes.--timeout <seconds>changes the wait.Check that you can send.
akedly whatsapp status akedly whatsapp diagnoseA finished wait confirms only that the account is connected. It does not confirm registered numbers, business verification or that sending is ready.
With more than one number, choose the one used for OTPs:
akedly whatsapp set-primary <phoneNumberId> --yes
Use the phoneNumberId from whatsapp status. It needs --yes because it changes the number your OTPs are sent from. If the account was already connected and nothing new happens in the dashboard, the wait times out. The CLI cannot see a Meta sign-up that was abandoned or failed.
Next: the WhatsApp reference and Your WhatsApp Business Account.
Replace an API key without downtime
Issue a new key, move your app to it, then revoke the old one with a grace period.
Create the new key.
akedly api-keys create --label <name> --secret-file <new path> --yesThe Secret is returned only once.
--secret-filewrites it to a new private file for your app's secret store and keeps it out of the output. Add--saveto also store it for the CLI's own Sending Commands.This key can use every pipeline, so the command needs
--yes. A key limited with--scope selected --pipeline-ids <ids>needs no--yes, unless you add--saveor--replaces-api-key-id.--saveneeds--yesbecause it changes the default key the CLI sends with.Deploy the new Secret.
Put the new Secret in your app's secret store and confirm your traffic works with it.
Revoke the old key.
akedly api-keys list akedly api-keys revoke <id> --grace-minutes <0-1440> --yes--grace-minutesis required: the old key keeps working for that many minutes, up to 24 hours.0stops it now.
Keep the Secret out of stdout
Without --save or --secret-file, the Secret is printed, and stdout can end up in agent transcripts and logs. Store it in a secret store, never on the command line.
api-keys create --replaces-api-key-id <id> --yesreplaces a key in one step, but the old Secret stops immediately. Use it only when downtime does not matter.api-keys createrecovers once by itself. After a network error or a server error it sends the request again with the same idempotency key, and if the response has no Secret it callsrecover-secretonce. If that still fails, follow the error hint, or runakedly api-keys recover-secretwith exactly one of--idempotency-keyor--api-key-id.akedly api-keys use <prefix>makes a saved key the default for this region;--secret-file <path>imports a key you already have.
Next: the API keys reference.
Configure a V1.2 pipeline
Create a pipeline with your real callback URLs, then use the returned id. The webhook Secret path must be new; keep the resulting file private.
akedly pipelines create --name "Website OTP" --api-version v1.2 --redirect-url https://example.com/verified --webhook-url https://example.com/webhooks/akedly --secret-file ./website-webhook-secret
akedly pipelines update <id> --verification-methods whatsapp,sms --method-order custom --otp-language en --status active --yes
akedly pipelines get <id>
Changing OTP language can provision its template on your connected WhatsApp account. The commands configure the pipeline; they do not prove message delivery. For a free fake-number verification cycle on this pipeline, run akedly quickstart --pipeline-id <id> --yes. Its dev-mode and webhook effects are described above.
Use pipeline settings for destination countries, protections and delivery policy. Add --dry-run to preview an update before saving.
Set up a V2 widget
Use your own callback endpoints. V2 requires both; create and activate the pipeline before attaching the widget.
akedly pipelines create --name "Website V2" --api-version v2 --redirect-url https://example.com/verified --webhook-url https://example.com/webhooks/akedly --secret-file ./v2-webhook-secret
akedly pipelines update <pipeline-id> --verification-methods whatsapp,sms --method-order custom --status active --yes
akedly widgets create --name "Website widget" --pipeline-id <pipeline-id> --company-name Example --widget-language en --secret-file ./website-widget-secret
akedly widgets get <widget-id>
Keep both Secret files. Widget Secrets cannot be revealed or recovered later. After a partial create, preserve the saved file and widgetId, then run the exact pipelines update command returned in details.recovery; do not create another widget to retry its pipeline settings.
Continue with the V2 start flow to integrate the widget in your app. Widget settings explains appearance, rate limits and pipeline-owned controls. A successful setup command is not a completed verification.
Use a library OTP template
Your own WhatsApp Business Account must be active. Find a library entry, then create the template using its exact name:
akedly whatsapp status
akedly whatsapp otp-templates library
akedly whatsapp otp-templates create --library-name <library-name> --languages en,ar
akedly whatsapp otp-templates list
Creation checks the requested languages' approval for up to 30 seconds. A pending approval still returns success because the template was saved; stderr gives the status and attach command. Wait until the language you need is approved, then attach it:
akedly pipelines update <pipeline-id> --otp-language en --otp-template <template-id> --yes
The pipeline needs an active WhatsApp method, your connected account and approval for its resulting OTP language. To restore the built-in template, use --otp-template default --yes.
TEMPLATE_PROVISIONING_FAILED means the template was saved. List it, then recover NOT_FOUND languages with akedly whatsapp otp-templates update <template-id> --add-languages en,ar; creating again can duplicate the operation. These commands remain available; the CLI's withdrawn authenticator enrollment is a separate feature.
Connect your own Turnstile keys
For a V1.2 Web integration, save the Cloudflare secret key in a private local file. Use only the public site key in the command and browser link.
akedly pipelines update <id> --turnstile on --turnstile-platform web --turnstile-site-key <public-site-key> --turnstile-secret-key-file <private-file> --yes
For new credentials, this first command is refused with TURNSTILE_SETUP_TOKEN_MISSING; its hint gives a link to the Turnstile setup-token helper with the public site key filled in. Add docs.akedly.io to that Cloudflare widget's Hostnames, open the link, then copy its token.
akedly pipelines update <id> --turnstile on --turnstile-platform web --turnstile-site-key <public-site-key> --turnstile-secret-key-file <private-file> --turnstile-test-token <fresh-token> --yes
akedly pipelines get <id>
The token works once and expires in five minutes. Generate another after a refused or uncertain save. Every key flag requires --turnstile on; the secret-file flag accepts - for piped stdin. --dry-run masks credentials, including secret query parameters and secret fields inside JSON text, but does not prove the key pair works.
Fit rate limits to your traffic
For a V1.2 pipeline, preview and apply recommendations from the selected period:
akedly pipelines update <pipeline-id> --recommended-limits --period last-month --dry-run
akedly pipelines update <pipeline-id> --recommended-limits --period last-month --yes
akedly pipelines get <pipeline-id>
This changes pipeline-wide limits with a 10% growth buffer, keeping phone/IP limits and breaker sensitivity. V1/V2 pipelines route the request to every attached widget, including inactive ones. To target one widget:
akedly widgets update <widget-id> --recommended-limits --period last-quarter --dry-run
akedly widgets update <widget-id> --recommended-limits --period last-quarter --yes
akedly widgets get <widget-id>
Widget recommendations use account-wide widget traffic, replace all 18 limits and enable/configure the circuit breaker. They do not change appearance, PoW or the breaker's trip state.
NOT_ENOUGH_TRAFFIC saves nothing: keep the current limits, choose a longer period, or supply your own pipeline or widget JSON file with --rate-limits-file. Recommendations cannot be combined with explicit limit files; widget recommendations also refuse breaker flags.
