wats.sh
Concepts

WATS Public API Surface

The public package surfaces that ship today versus planned parity work.

active · applies to 0.3.x-alpha-tooling · reviewed 2026-05-02

For full signatures and behavior, see the reference.

shape-only versus live-validated: MockTransport tests, local crypto, synthetic webhooks, and consumer fixtures prove a WATS API shape is implemented — they do not prove Meta accepted that behavior in a live account. Live validation is credential-gated and tracked in the parity matrix. The default repository checks never call Meta.

Current package surfaces

@wats/types

Shared TypeScript contracts for WhatsApp domain payloads.

Primary exports:

  • client config types
  • webhook envelope/change/value types
  • 14-variant WhatsAppMessage union
  • status, contact, and error payload types

Status: foundations-complete for shared domain contracts; deeper runtime normalization continues under parity work.

@wats/crypto

Portable crypto provider seam.

Primary exports:

  • CryptoProvider
  • createCryptoProvider
  • Node/Bun adapter subpath: @wats/crypto/node
  • WebCrypto adapter subpath: @wats/crypto/webcrypto
  • typed crypto errors

Status: foundations-complete.

@wats/graph

Graph transport and endpoint substrate.

Primary exports:

  • GraphClient
  • createFetchTransport
  • createMockTransport via @wats/graph/testing
  • Transport types
  • defineEndpoint
  • sendMessage for POST /{phoneNumberId}/messages
  • sendMarketingTemplate / buildSendMarketingTemplatePayload for POST /{phoneNumberId}/marketing_messages
  • Calling API lifecycle and permission callables: initiateCall, preAcceptCall, acceptCall, rejectCall, terminateCall, getCallPermissions
  • outbound message payload builders for text, media, location, contacts, reaction, interactive, template, read, typing, Marketing Messages, call-button, and deep-link sends
  • PhoneNumberClient with message composer helpers, one-call media upload/send helpers, calling lifecycle helpers, phone registration lifecycle, QR code CRUD, business public-key helpers, phone inventory/profile/settings helpers, profile/commerce mutation helpers (updateBusinessProfile, updateCommerceSettings), Block API/OBA/display-name helpers, and Groups helpers (createGroup, listGroups, group(groupId))
  • GroupClient with bound-id Groups methods for getInfo, update, delete, invite links, participants, and join requests
  • WABAClient with WABA/phone-number inventory, WABA callback override, phone-number creation, advanced template helpers, Template Groups, and Flow helpers
  • business/admin callables/types: read-only business/admin inventory (getWabaInfo, listSubscribedApps, listPhoneNumbers, getPhoneNumberInfo, getPhoneNumberSettings, getBusinessProfile, getCommerceSettings), profile/commerce/settings updates, Block API/OBA/display-name helpers, phone registration lifecycle, QR code CRUD, business public-key helpers, Embedded Signup token exchange, and WABA callback override, exported at root and at ./endpoints/business-management where applicable. WATS maps public camelCase names to Graph snake_case at the transport boundary.
  • public endpoint subpaths: @wats/graph/endpoints/messages, @wats/graph/endpoints/media, @wats/graph/endpoints/templates, @wats/graph/endpoints/flows, @wats/graph/endpoints/calling, @wats/graph/endpoints/business-management, and @wats/graph/endpoints/groups. bun run api:check keeps package exports, fixture imports, docs, and changelog mentions aligned
  • Node/Bun-only filesystem media helpers: @wats/graph/node-media exports path-based uploadAndSend*FromPath helpers. This subpath is deliberately separate from the root entrypoint so browser/edge users never pull node:fs transitively.
  • paginate / paginateAll
  • Graph error classes and error registry helpers
  • media runtime: uploadMedia, downloadMedia, downloadMediaBytes, deleteMedia, decryptEncryptedMedia, upload-session helpers, MediaValidationError, MediaCryptoError, MediaIntegrityError, and finite media cap constants

Status: foundations-complete for Graph plumbing. Media runtime, outbound composers, template helpers, Flow helpers, Calling request/webhook shapes, Groups request shapes, and bounded business/admin helpers are complete for credential-free MockTransport-backed behavior. Live Meta checks, automatic user-block decisions, policy/appeal automation, catalog CRUD, and remaining WABA admin APIs remain credential-gated.

@wats/core

Runtime orchestration and typed update handling.

Primary exports:

  • normalizeWebhookEnvelope with message/status/account/unknown/calling update variants and deep camelCase normalization for common message body families
  • legacy raw parser/router helpers: parseWebhookUpdate, createUpdateRouterdeprecated, marked @deprecated at the type level; superseded by normalizeWebhookEnvelope + TypedRouter and scheduled for barrel removal next minor
  • typed filter namespace and @wats/core/filtersTyped, including filtersTyped.call and message.* helpers for media, location, reaction, interactive replies, and quick-reply buttons
  • legacy raw filter namespace and @wats/core/filtersdeprecated, marked @deprecated at the type level; superseded by filtersTyped and scheduled for barrel removal next minor
  • TypedRouter
  • createListenerRegistry
  • WhatsApp facade and the createWhatsApp(...) factory, including sendText(...) (alias startChat(...)), onMessage/onStatus, and composer helpers when phoneNumberId is bound

The WhatsApp facade binds:

  • a mandatory GraphClient
  • optional PhoneNumberClient when phoneNumberId is provided
  • optional WABAClient when wabaId is provided
  • a TypedRouter
  • optional listener registry support through .listen(...)

Status: foundations-complete for typed routing/listening/facade behavior; calling webhook variants and calling typed filters work against credential-free synthetic payloads.

@wats/http

Webhook verification and HTTP adapter boundary.

Primary exports:

  • verifyWebhookChallenge
  • validateWebhookSignature
  • createWebhookAdapter
  • createFetchWebhookHandler
  • createBunWebhookServer
  • createNodeWebhookHandler
  • webhook adapter request/response/config/error types

Status: foundations-complete for runtime-neutral webhook ingestion.

@wats/config

Application-edge config substrate.

Primary exports:

  • validateConfig
  • parseConfig
  • loadConfig
  • redactConfig
  • ConfigValidationError
  • WatsConfig and related config types

Status: experimental baseline for YAML/JSON onboarding and env-secret references.

@wats/cli

Package-manager CLI surface for safe onboarding and local inspection.

Primary exports:

  • runCli
  • createWebhookVerifyToken
  • wats bin

Current commands:

  • wats --help
  • wats init [dir] [--dry-run] [--format yaml|json] [--profile <name>]
  • wats init --help
  • wats setup
  • wats onboarding
  • wats --version
  • wats upgrade / wats update
  • wats config validate <path>
  • wats config validate --config <path>
  • wats doctor --help
  • wats openapi --config <path>
  • wats openapi --config <path> --profile <name>
  • wats openapi --config <path> --server-url <url>
  • wats openapi --config <path> --out <path>
  • wats openapi --help
  • wats serve --config <path> --dry-run [--profile <name>] [--host <host>] [--port <port>] [--print-routes]
  • wats serve --config <path> --paas [--profile <name>] [--print-routes]
  • wats serve --config <path> --live --yes-live --env-file .env.local [--profile <name>] [--host <host>] [--port <port>]
  • wats serve --help
  • wats webhook token
  • wats messages list [--config <path>] [--profile <name>] [--env-file <path>] [--limit N] [--cursor <rowId>] [--json]
  • wats messages show <message-id> [--config <path>] [--profile <name>] [--env-file <path>] [--json]
  • wats messages --help

Status: experimental CLI foundation. It generates config/env placeholder files, validates config files safely, exports service OpenAPI, runs offline diagnostics, starts a dry-run local service, starts a credential-gated local live service behind explicit --live --yes-live --env-file .env.local, generates local webhook verify tokens, and lists/shows locally projected messages through the service API (wats messages list/show). It never reads .env.local implicitly and never calls Meta Graph unless you start live serve and hit a service route.

@wats/service

Runtime-neutral standalone webhook/API service foundation.

Primary exports:

  • createWatsServiceApp
  • createWatsServiceOpenApiDocument
  • WatsServiceApp
  • WatsServiceConfig
  • WatsServiceOpenApiOptions
  • WatsServiceOpenApiDocument
  • WatsServiceError

Current routes:

  • GET /healthz
  • GET /readyz
  • GET /openapi.json
  • GET profile.webhook.path
  • POST profile.webhook.path
  • POST {profile.service.apiPrefix}/messages/text
  • POST {profile.service.apiPrefix}/messages
  • GET {profile.service.apiPrefix}/messages
  • GET {profile.service.apiPrefix}/messages/{messageId}
  • opt-in Groups routes when enableGroupRoutes is true

Status: experimental service foundation. It composes config profile shape, explicit resolved secrets, Graph client, WebhookAdapter, WhatsApp facade, optional PersistenceStore injection, optional enableGroupRoutes, and a generated OpenAPI 3.1 document for the routes above. The CLI dry-run and local live wrappers can serve it locally; production hosting hardening and background outbox workers are later work.

@wats/persistence

Local persistence contracts, SQLite adapter, and Postgres adapter.

Primary exports:

  • PersistenceStore
  • MigrationReport
  • PersistenceHealth
  • PersistenceError
  • CURRENT_SCHEMA_VERSION
  • outbox record APIs on PersistenceStore
  • runOutboxWorkerOnce
  • createSqlitePersistence from @wats/persistence/sqlite
  • createPostgresPersistence from @wats/persistence/postgres (shape-only, mock-client tested)

Status: experimental local persistence foundation. SQLite migrations, schema metadata, migration locks, webhook-event/request-idempotency/outbox tables, outbox record APIs, a one-tick at-least-once worker helper, redacted health diagnostics, and optional @wats/service injection exist. The Postgres adapter ships at @wats/persistence/postgres as shape-only, mock-client tested; it is not live-validated against a running Postgres service in default CI. Read-only local message projection is reachable through wats messages list/show; deeper conversation/thread navigation, status UI wiring, automatic service send enqueueing, and production hosting are later work.

Internal support and workspace packages

  • @wats/internal-utils — published internal support required by public runtime packages such as @wats/config; not a stable application API.
  • @wats/testing — private workspace fixtures and policy tests; never published.

Explicit non-surfaces today

Not implemented as runtime APIs yet:

  • live credentialed template mutations/validation beyond the shape-only helpers
  • Flow hosting and live Flow data-channel validation beyond credential-free helpers
  • live calling sessions and WebRTC/media signaling beyond the credential-free Calling API request/webhook helpers
  • remaining WABA/admin APIs such as WABA CRUD, catalog/product inventory CRUD, phone-level callback override, and automatic user-block policy/appeal automation
  • full Meta Graph API OpenAPI generation
  • config persistence schema, deeper CLI message/thread navigation, conversation APIs, and automatic service send enqueueing
  • production Docker/Compose support, container image publication, or container-registry workflow

See the roadmap for what is planned versus out of scope.

Release compatibility labels

  • Stable foundations: @wats/types, @wats/crypto, Graph transport/client/error substrate, webhook adapter, normalizer, filters, router, listeners, facade.
  • Experimental / expanding: endpoint catalog breadth, media runtime, template/Flow/calling management helpers, config, CLI, service, persistence, OpenAPI, docs site.
  • Internal support / private: @wats/internal-utils is published internal support for runtime dependency closure; @wats/testing stays private.

See the release policy for versioning rules and the API stability policy for the stable-for-0.x, experimental, and internal labels.

On this page