# Changelog

Changes to the PaalChat API.

## 2026-10-04

- **Self-serve accounts: trust rules.** Accounts that sign up themselves verify their phone by
  SMS before sending templates (`account_not_verified`), and new accounts have a daily limit of
  business-initiated messages that rises with the account's age and record
  (`sending_limit_reached`). When Meta flags a number's quality, the business's campaigns pause.
  Products PaalTech set up are not affected by the limits.
- **AI assistant (dashboard)**: self-serve businesses can switch on an assistant that answers
  customers from what they teach it (FAQs, text, documents, web pages) - Suggest drafts replies
  for staff, Auto replies and hands over to people. Scoped to the business's own purpose, per
  WhatsApp's rules. No API changes yet; assistant settings through the API come next.

## 2026-10-03

- **Arkesel SMS**: SMS can go through Arkesel (now the default for new SMS setups) or Hubtel,
  chosen per business with `provider` on [Set up SMS or email](/docs/api/enable-channel). A
  business may send with its own Arkesel account (`arkesel.api_key`, checked and stored
  encrypted; `own_key` on the connection). New errors `invalid_provider_credentials` and
  `provider_unavailable`; `arkesel` in provider health.
- **Inbox, Connect and status pages**: light and dark themes (following the device by default),
  a refreshed design, and an inbox that shows delivery ticks on each reply. No API changes.

## 2026-10-02

- **PaalChat billing** (off until prices are published): plans with limits and features, Get
  billing (PaalChat and Meta shown apart), invoices paid through Paystack. New scope
  `billing.manage`; errors `plan_limit_reached`, `plan_feature_missing`, `payment_unavailable`.
- **SMS, email and failover**: SMS through Hubtel and email through Resend per business
  (`channel` on Send message), notifications that fall back between channels
  (`notification.updated`), and provider health (`GET /providers`). Errors
  `channel_not_enabled`, `channel_not_allowed`.
- **Operations**: a public [status page](/status) (and `/status.json`), and WhatsApp account
  transfers between businesses that both sides approve (`whatsapp.connection` events
  `transfer_requested`, `transferred_out`, `transferred_in`).
- **Automations**: triggers (message received, keyword, contact created, conversation status,
  date field), conditions, steps with waits, run logs, and the `automation.action` callback.
  New scopes `automations.read` / `automations.manage`.
- **Segments, scheduling and campaigns**: saved segments over contact fields, tags and consent;
  `send_at` on template sends with Cancel scheduled message (status `cancelled`); campaigns with
  preview (skips, estimated Meta cost), pacing, repeat, pause/resume/cancel and results
  (`campaign.updated`). Scopes `campaigns.read` / `campaigns.manage` are now in use.
- **Templates as a product**: template versions and history (removed templates are kept),
  parameters checked before sending (`invalid_template_parameters`), and a template library
  for schools and shops. **Fix**: templates created through the API now reach Meta with their
  full components (text and examples were dropped before).
- **Meta usage estimates**: Get Meta usage (per number and category, compared with Meta's own
  analytics) and Estimate Meta cost for an audience. Estimates only; Meta bills businesses directly.
- **Data rights**: per-business retention (`retention.message_content_days`), Export business
  data, and Erase contact; new ability `data.manage`.
- **Consent and quiet hours**: STOP/START replies, Record consent, notification preferences,
  a suppression list, and business quiet hours with time zones - checked before every
  business-initiated template. New callback `contact.consent`; new fields `category`, `topic`,
  `urgent` on Send message and `scheduled_for` on messages; ability `messages.urgent`.
- **PHP SDK and Laravel package** (`paaltech/paalchat-php`, `paaltech/paalchat-laravel`) and a
  written **versioning policy**; responses carry `X-PaalChat-API-Version`, and deprecated
  endpoints will carry `Deprecation` and `Sunset` headers.
- **API keys**: `sk_live_` and `sk_test_` keys, revocable, optionally tied to IP addresses;
  `GET /me` shows the key's `environment` and `prefix`. Older `ptw_` tokens keep working.
- **Sandbox**: test keys work on sandbox businesses with simulated WhatsApp - connect in one
  click, simulate incoming messages and delivery statuses. Callbacks carry `sandbox`.
- **Idempotency-Key** header on every write; **per-business rate limit** (120/minute) and
  optional daily message cap; **Get usage** for PaalChat usage per day.
- **Inbox**: a business's staff work their conversations in PaalChat, signed in from your
  product with a one-time link (Sign staff in to the inbox). Roles admin, agent and viewer;
  remove access when staff leave. Conversations have an `assignee` (an inbox member), set
  through Update conversation. New ability `inbox.manage`, error `unknown_member`.
- **Media**: incoming attachments are downloaded and stored by PaalChat (`media_id` on
  `message.received`, then a `media.updated` callback with a 15-minute signed link); upload
  files and send image, video, audio and document messages. Endpoints Upload media and Get
  media; errors `feature_disabled`, `unknown_media`, `media_not_ready`,
  `media_type_mismatch`, `unsupported_media`, `media_too_large`. Enabled per business.

## 2026-10-01

- **Templates through the API**: create (submitted to Meta for review) and delete (one
  language or all) with the `templates.manage` scope. New errors `template_rejected`,
  `waba_required`, `meta_unavailable`.
- **Contacts and conversations API**: list, get and upsert contacts (your own `external_id`,
  custom fields, tags), define custom fields, list and work conversations (status,
  priority, tags, read), read their messages with content, add internal notes. New
  scopes `conversations.read` / `conversations.manage`; new events `contact.created`,
  `contact.updated`, `conversation.created`, `conversation.updated`. Messages and their
  callbacks carry `contact_id` and `conversation_id`. See [Contacts and conversations](/docs/contacts-conversations).
- PaalChat now keeps each business's **contacts and conversations**, and the content of
  messages (encrypted, 365 days by default) - see the [FAQ](/docs/faq). API access
  to them is coming.
- A product can have several webhook endpoints, each with its own secret and an
  optional filter by event, business or channel - see [Callbacks](/docs/callbacks#several-endpoints).
  Your existing callback URL is your default endpoint and receives everything, as before.
- Every response carries `X-Request-ID` (send your own to correlate), repeated in error
  bodies as `error.request_id` - see [Errors](/docs/errors#request-ids).
- **Token scopes renamed** to `<resource>.<action>`: `businesses.read`, `businesses.write`,
  `connections.read`, `connections.manage`, `templates.read`, `messages.read`,
  `messages.send` (plus reserved scopes for coming endpoints). Existing tokens were
  converted automatically - see [Authentication](/docs/authentication).
- Messages carry Meta's `pricing` (billable, category, type, model) in the message
  resource and `message.status`. New guide: [WhatsApp pricing](/docs/pricing).
- New message status `unknown`: Meta's answer to a send was lost, so it may or may not
  have been delivered; it is never resent automatically.
- The 24-hour window is checked per sending number, as Meta applies it.
- Connect links accept a `return_url` only on your product's registered origins
  (`422 return_url_not_allowed`).
- "Free text" is now called "free-form text" in the docs.
- **Connection states** are now `pending`, `connecting`, `connected`, `degraded`,
  `maintenance`, `suspended`, `revoked` and `disconnected` (`error` is gone - see
  [Connection states](/docs/connect-whatsapp#connection-states)), with matching
  `whatsapp.connection` events. New `409 connection_paused`.
- A WhatsApp account's `health.credential` (a status) is now `health.has_credential`
  (true/false); the account's own `status` says whether it works.

## 2026-09-30 - v1

- Businesses: list, get, create or update by `external_id`.
- WhatsApp: hosted Embedded Signup connect links, connection state and health, phone numbers, templates, disconnect.
- Messages: send text and template messages with idempotent references; read a message's status.
- Callbacks: `message.received`, `message.status`, `template.status`, `whatsapp.connection`, signed with `X-PaalChat-Signature`.
- One error format for every endpoint: `{"error": {"code", "message"}}`.
