1app Grow

Developer API

Send transactional email, SMS OTPs, and WhatsApp authentication messages from your apps — scoped to your workspace providers.

Base URL

https://grow.1app.online/api/v1/

Auth

Bearer token with read + write abilities

Use this API to send transactional messages and manage marketing data from external applications such as 1app.

Production base URL: https://grow.1app.online/api/v1/

In-app guide: Sidebar Developers (/developers) or Settings → Developer API

Full API reference (public): /developers/docs — styled HTML; raw markdown at /developers/docs/raw

Postman: Collection · Environment — import into Postman, set apiToken, and run requests.


Delivery behaviour

Transactional API sends are immediate — they do not enter the campaign queue.

Path Behaviour
POST /messages/* Synchronous HTTP: provider is called in the same request; response includes sent or failed.
Campaign broadcasts Queued separately with rate limiting — transactional sends are not delayed by active campaigns.

OTP and other transactional traffic from 1app will not wait behind an active WhatsApp/SMS/email campaign. For best isolation during large broadcasts, use a dedicated WhatsApp number for authentication templates.


Postman

  1. Download the Postman collection (optional environment).
  2. In Postman: Import → upload the JSON file, or Import → Link and paste the collection URL.
  3. Set collection variable apiToken to your API token (read + write).
  4. Confirm baseUrl matches your deployment (defaults to this server's /api/v1 URL on download).

The collection includes transactional sends (WhatsApp/SMS OTP, email, SMS, templates), contacts, lists, campaigns, and lead submission.


Authentication

  1. Log in to 1app Grow and select the workspace that has your email/SMS/WhatsApp providers configured.
  2. Open Profile → API Tokens and create a token.
  3. Enable both permissions on the token:
    • write — required for sending messages and creating/updating contacts and lists
    • read — required for listing resources and checking message delivery status

If you see "Invalid ability provided.", your token is missing write. Recreate the token and check read + write (not legacy create/update/delete labels).

Send the token on every request:

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: application/json

The API uses the currently selected workspace on the user account that owns the token. Create separate tokens per workspace if you operate multiple tenants.


Idempotency

Transactional send endpoints accept an idempotency key to prevent duplicate sends when your client retries:

  • Header: Idempotency-Key: unique-string-per-attempt
  • Or JSON body field: "idempotency_key": "unique-string-per-attempt"

If the same key is reused for the same workspace, the original message record is returned instead of sending again.


Transactional messaging

All send endpoints require the write ability and are rate-limited to 300 requests per minute per token.

POST /messages/whatsapp/otp

Sends a one-time code using an AUTHENTICATION category WhatsApp template approved in Meta.

Body

Field Required Description
to yes E.164 phone number, e.g. +2348012345678
code yes OTP string, max 15 characters (Meta authentication limit)
template no* Meta template name (meta_template_name in Grow)
language no Template language code, default en
from no Sender phone number exactly as shown in Grow (WhatsApp → Numbers), e.g. +2348012345678
whatsapp_number_id no Alternative to from — numeric ID from GET /whatsapp-numbers
idempotency_key no See Idempotency

Use from or whatsapp_number_id, not both. If neither is set, the first active workspace number is used.

*Required unless your workspace administrator has configured a default OTP template.

Example

curl -X POST "https://grow.1app.online/api/v1/messages/whatsapp/otp" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: verify-user-9912" \
  -d '{
    "to": "+2348012345678",
    "code": "482910",
    "template": "1app_verify",
    "language": "en"
  }'

Prerequisites

  • Active WhatsApp number on the workspace (WhatsApp → Numbers)
  • Approved AUTHENTICATION template synced in Grow (WhatsApp → Templates)

WhatsApp sender number

Pass the sender as from using the phone number shown in Grow under WhatsApp → Numbers (international format, e.g. +2348012345678).

If from is not on your workspace, the API returns HTTP 422:

{
  "status": "failed",
  "error": "The sender phone number is not registered on this workspace."
}

Alternatively, pass whatsapp_number_id from GET /whatsapp-numbers. If neither is set, the first active number on the workspace is used.

{
  "to": "+2348012345678",
  "code": "482910",
  "template": "1app_verify",
  "from": "+2349087654321"
}

The template must be approved on that specific number.


SMS OTP

POST /messages/sms/otp
Field Required Description
to yes E.164 phone number
code yes OTP string
message no Custom template; :code is replaced. Default: Your verification code is :code
idempotency_key no See Idempotency

Example

{
  "to": "+2348012345678",
  "code": "482910"
}

Transactional email

POST /messages/email
Field Required Description
to yes Recipient email
subject yes Email subject
html yes HTML body
idempotency_key no See Idempotency

Free-form SMS

POST /messages/sms
Field Required Description
to yes E.164 phone number
body yes Message text (max 320 chars)
idempotency_key no See Idempotency

WhatsApp template (non-OTP)

POST /messages/whatsapp
Field Required Description
to yes E.164 phone number
template yes Meta template name
language no Default en
variables no Array of template variable values in order
from no Sender phone as shown in Grow (see WhatsApp sender number)
whatsapp_number_id no Alternative sender selector by ID
idempotency_key no See Idempotency

Message status

GET /messages/{id}

Requires read ability. Returns delivery status for a message sent in the current workspace.

Response

{
  "id": 42,
  "channel": "whatsapp",
  "to": "+2348012345678",
  "status": "sent",
  "provider_message_id": "wamid.xxx",
  "error": null,
  "idempotency_key": "verify-user-9912",
  "sent_at": "2026-06-05T12:00:00+00:00",
  "created_at": "2026-06-05T11:59:58+00:00"
}

status is one of: queued, sent, failed.


Send response format

Successful send (HTTP 201):

{
  "id": 42,
  "channel": "whatsapp",
  "to": "+2348012345678",
  "status": "sent",
  "provider_message_id": "wamid.xxx",
  "sent_at": "2026-06-05T12:00:00+00:00"
}

Failed send (HTTP 422):

{
  "id": 43,
  "channel": "whatsapp",
  "to": "+2348012345678",
  "status": "failed",
  "error": "No active WhatsApp number configured for this workspace."
}

Common errors:

Error Fix
No active WhatsApp number Connect a number under WhatsApp → Numbers
No active SMS/email provider Add provider under SMS or Email settings
WhatsApp OTP template not configured Pass template in the request body
OTP code must be 15 characters or fewer Shorten the code for authentication templates
No workspace associated with this token User must belong to a workspace; switch workspace and recreate token

Integrating from 1app

Typical phone verification flow:

  1. User enters phone number in 1app.
  2. 1app backend generates a 6-digit OTP and stores it (cache/DB) with expiry.
  3. 1app backend calls POST /messages/whatsapp/otp (or /messages/sms/otp) on Grow with a unique Idempotency-Key per verification session.
  4. User enters OTP in 1app; 1app validates locally.
  5. Optionally poll GET /messages/{id} if you need provider-level confirmation.

PHP (Laravel) example

use Illuminate\Support\Facades\Http;

$response = Http::withToken(config('services.grow.api_token'))
    ->withHeaders(['Idempotency-Key' => "otp-{$userId}-".now()->timestamp])
    ->post(config('services.grow.base_url').'/messages/whatsapp/otp', [
        'to' => $phoneE164,
        'code' => $otp,
        'template' => config('services.grow.whatsapp_otp_template'),
        'language' => 'en',
    ]);

if ($response->failed()) {
    report($response->json('error'));
}

Suggested .env on 1app:

GROW_API_BASE_URL=https://grow.1app.online/api/v1
GROW_API_TOKEN=your_sanctum_token
GROW_WHATSAPP_OTP_TEMPLATE=1app_verify

Contacts & lists (CRUD)

Endpoint Methods Ability
/contacts GET, POST read / write
/contacts/{id} GET, PUT, DELETE read / write
/lists GET, POST read / write
/lists/{id} GET, PUT, DELETE read / write
/lists/{id}/contacts GET read

Campaigns (read-only)

Endpoint Methods Ability
/campaigns GET read
/campaigns/{id} GET read
/campaigns/{id}/logs GET read

Lead capture

POST /leads

Authenticated lead ingestion. Requires a valid API token.

Field Required Description
name yes Contact name
email no Email address
phone no Phone number
source no api, meta_ads, or tiktok_ads
form_slug no Link submission to an existing lead form
custom_fields no Key-value object for extra data

Errors

All /api/v1/* responses are JSON. Stack traces and internal exception details are never returned.

HTTP status codes

HTTP Meaning
401 Missing or invalid token
403 Token lacks required ability — see error and required_abilities
404 Endpoint or resource not found (wrong workspace returns 404 for scoped resources)
422 Validation failure or business/send failure — see error and optional errors
429 Rate limit exceeded — see retry_after_seconds when present
500 Unexpected server error — generic message only

Response shapes

Authentication (401)

{ "error": "Authentication required. Provide a valid API token: Authorization: Bearer {token}" }

Missing permission (403)

{
  "error": "This endpoint requires the write permission on your API token. Create a new token with read + write enabled.",
  "required_abilities": ["write"]
}

No workspace on token (422)

{
  "error": "No workspace associated with this token. Open Grow, switch to the correct workspace, then create a new API token."
}

Validation (422)

{
  "error": "The given data was invalid.",
  "errors": { "name": ["The name field is required."] }
}

Send failure (422) — transactional endpoints

{
  "id": 43,
  "channel": "whatsapp",
  "to": "+2348012345678",
  "status": "failed",
  "error": "The sender phone number is not registered on this workspace."
}

Not found (404)

{ "error": "Resource not found." }

Support

  • Configure providers in Settings before calling send endpoints.
  • Workspace admins: use the in-app Developers page for live base URL, template names, and Postman collection.
  • Platform issues: contact your 1app Grow administrator.

Need a workspace with providers configured?

Start free trial