Skip to content
Documentation

WhatsApp messaging

Connect a number, create approved templates, send messages, and track delivery — by hand or from your code.

This is the end-to-end guide to sending on WhatsApp with Darkel. It follows the natural order: connect a number, get a template approved, send, then track what happened.

How sending works

WhatsApp does not let businesses send arbitrary text out of the blue. To start a conversation you must use a template that Meta has reviewed and approved. Darkel sends are therefore always template-based — you pick an approved template and fill in its variables.

  • You need a connected number to send from (your own, or a shared Darkel number).
  • You need at least one approved template.
  • You need a funded prepaid balance with WhatsApp enabled.

Template-only sending is a feature, not a limitation: an approved template delivers to your customer regardless of WhatsApp’s 24-hour reply window. You never have to worry about “the session expired”.

Connect a number

Open WhatsApp in the dashboard. You have two paths:

Option A — Bring your own number (recommended)

Messages arrive from your own verified business name and number, so customers see you rather than a number they do not recognise. You keep ownership of the WhatsApp Business Account, your template library is yours to author, and Meta bills you directly for conversations. Connect it in a few clicks through Meta’s secure Embedded Sign-up.

Start here if you can. Sending under your own business identity earns more trust, keeps your sender reputation in your hands, and lets you write your own templates without waiting on us.

  1. Start the secure sign-up

    Click “Connect WhatsApp”. This opens Meta’s official Embedded Sign-up in a popup.

  2. Pick your business & number

    Sign in to Facebook, choose (or create) your WhatsApp Business Account, and select the phone number to send from.

  3. Finish

    Meta hands the connection back to Darkel and we securely store the access it grants. Your verified business name and number then show in the dashboard.

Option B — Use a shared Darkel number

If connecting your own number is not practical yet — no WhatsApp Business Account, no verified business, or you simply want to send today — start on a Darkel-managed number instead. There is no Meta setup and no Meta billing to configure, and it is the default in sandbox. Each message is charged to your Darkel balance at Meta’s price for its type and the recipient’s country, converted to naira at Darkel’s published rate with no markup — see the price list. Templates on a shared number are curated by us rather than authored by you, and messages arrive from a Darkel number rather than your brand. You can move to your own number later without changing any code.

With your own number, Meta bills you directly for WhatsApp conversations — Darkel adds no per-message charge — and your access credentials are encrypted at rest — Darkel never exposes them.

Billing eligibility (own number)

If a message is accepted but never delivered, the most common cause is that your WhatsApp Business Account has no active payment method with Meta (Meta error 131042). Add a payment method to your WABA in Meta Business settings. See Delivery & errors.

Create & manage templates

A template is a reusable message with placeholders for the bits that change. Meta reviews each template before it can be used. There are three categories:

CategoryUse forWho writes the text
UtilityOrder updates, reminders, receiptsYou
MarketingPromotions, offers, announcementsYou
AuthenticationOne-time passcodes (OTP)Meta — you only supply the code

Creating a template (your own number)

  1. Name it

    Use lowercase letters, numbers and underscores, e.g. order_confirmation. The name is how you reference it when sending.

  2. Write the body with placeholders

    Use {{1}}, {{2}} … where values vary, e.g. “Hi {{1}}, your order {{2}} is on its way.”

  3. Pick a category & language

    Choose Utility, Marketing or Authentication and the language code (default en_US).

  4. Submit for review

    Meta typically approves within minutes to a few hours. Status shows as pending → approved (or rejected, with a reason).

Authentication templates

For OTPs, Meta supplies the wording (e.g. “{{1}} is your verification code”) and adds a copy-code button. You only choose an optional code-expiry time and, when sending, pass the code itself. You do not write the body.

Using a shared number?

Templates on a shared Darkel number are curated for you — browse the available ones in the dashboard. If you need a new template on a shared number, contact us. To author your own templates freely, connect your own number.

Moving to your own number? Templates do not come with you

An approved template lives on the WhatsApp account that owns it. When you connect your own number you create and submit your templates again on your own account, and they get their own approvals. A template you write there can differ from the shared one it replaces — so re-check the variables your send code passes, because a mismatch is rejected with 132000.

Send a message

Once you have an approved template, sending is the same idea everywhere: name the template, give the recipient, and supply the variable values via components.

From the dashboard

Go to WhatsApp → Send, pick a template, choose the recipient, fill in the variables, and send. Great for one-offs and for confirming a template works before you automate it.

From your code

POST/v1/whatsapp/messagesX-Api-Key

Send a template message from the workspace that owns the key.

Request body
{
  "to": "+2348012345678",
  "template": {
    "name": "order_confirmation",
    "languageCode": "en_US",
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Ada" },
          { "type": "text", "text": "DK-1042" }
        ]
      }
    ]
  }
}
FieldRequiredNotes
toYesRecipient in E.164 format, e.g. +2348012345678
template.nameYesExact name of an approved template
template.languageCodeNoDefaults to en_US; must match the template’s language
template.componentsSometimesRequired if the template has variables; the order of parameters maps to {{1}}, {{2}} …

Mapping placeholders

The first item in body parameters fills {{1}}, the second fills {{2}}, and so on. A template with no placeholders can be sent with no components at all.

Parameter limits & formatting

Every parameter value must be a single line: no line breaks, tabs, or 4 or more consecutive spaces. Authentication templates additionally cap each value (the code) at 15 characters — they are meant for short verification codes, not names or sentences. Other categories (Utility, Marketing) allow longer values, up to the 1024-character body limit. A value that breaks these rules is rejected with a 400 before it reaches WhatsApp — so put long content in a Utility/Marketing template, not an Authentication one.

Template categoryMax length per parameter
Authentication15 characters
UtilityUp to the 1024-char body limit
MarketingUp to the 1024-char body limit

Sending an OTP (authentication template)

Authentication templates carry a short verification code plus a Copy code button. You must send the code twice — once in the body and once in the button — or the Copy code button will not appear. Every parameter is capped at 15 characters.

Match your own template, not the example

A template belongs to the WhatsApp account it was created on. The first example below is Darkel’s shared otp_verification, whose body takes two variables. The moment you send on your own number, only the templates you created on your own WhatsApp account exist — the same name is still a different template, with whatever variables you gave it. Send more or fewer parameters than your template’s {{n}} placeholders and WhatsApp rejects it with 132000; a name or language that does not exist on your account is 132001. Check the exact shape under WhatsApp → Templates before you automate.

On the SHARED Darkel number — {{1}} is the code, {{2}} your service name
{
  "to": "+2348012345678",
  "template": {
    "name": "otp_verification",
    "languageCode": "en_US",
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "399399" },
          { "type": "text", "text": "Acme Ltd" }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          { "type": "text", "text": "399399" }
        ]
      }
    ]
  }
}
On YOUR OWN number — a Meta authentication template takes the code only
{
  "to": "+2348012345678",
  "template": {
    "name": "otp_verification",
    "languageCode": "en_US",
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "399399" }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          { "type": "text", "text": "399399" }
        ]
      }
    ]
  }
}

The Copy code button is required

The button component is not optional when your template has a Copy code button — omit it and the send is rejected (131008) or the button is dropped. Use sub_type: "url", a numeric index: 0 (a string index silently drops the button), and put the same code as the body. Drop the button component only if your own template genuinely has no button. Keep every value ≤ 15 characters.

Track delivery & replies

Every send returns a message record immediately, then progresses through statuses as WhatsApp reports back:

StatusMeaning
pendingAccepted by Darkel, being handed to WhatsApp
sentWhatsApp accepted it
deliveredReached the recipient’s device
readThe recipient opened it
failedDelivery failed — the full price is refunded automatically
  • See the full history under WhatsApp → Messages in the dashboard, searchable by number, template or text.
  • When a customer replies, the inbound message is captured and attributed to your workspace.
  • Each message record has a pricing object — see API reference. Charges and refunds are in Billing & pricing.
  • Statuses, automatic refunds and Meta error codes are explained in Delivery & errors.

Testing in the sandbox

  1. Create your sandbox

    From the dashboard, spin up your free sandbox workspace. It comes with play money and a shared test number.

  2. Use approved test recipients

    Sandbox sends only reach numbers on the approved test list — the dashboard shows them, and the send screen offers them as choices. Ask us to add more if needed.

  3. Send with a dk_test_ key

    Create a dk_test_ key in the sandbox and send exactly as you would in production — same endpoint, same body. Only the key differs.

  4. Go live

    When it works end-to-end, switch to your live workspace, connect/confirm your number, fund the balance, and swap in a dk_live_ key.