testMode field to identify Test Numbers; do not infer it
from the ID or convert the ID to a JavaScript number.
Channel message actions also use the Polymorfa message id. The numeric
position returned by channel reads is only a pagination cursor. See
Channel messages.
API method pages include cURL and SDK preview examples alongside their
parameters, responses, and interactive request playground. SDK preview examples
show the intended client call, but they are not an installation or release
announcement. Use the cURL example for an executable request today.
Do not install unverified names
A package name alone does not prove that Polymorfa publishes or maintains the artifact. Install an SDK only when its exact package name and version appear in the Changelog and this page. Before installing a future SDK release, verify all of the following:- The package and version appear in a Polymorfa changelog entry.
- The registry publisher and repository link point to an official Polymorfa organization.
- The install name exactly matches the name in these docs.
- The package version supports the API date you intend to use.
Use the API directly
id and
createdAt. Machine operation IDs are code-generation details; customer-facing
method names and URLs are organized by task in the Guides navigation.
Handle outbound call limits
POST /messaging/voip/calls returns 429 when the source session reaches its
outbound-start limit. The limit applies across server keys and client tokens;
client-token setup and concurrency limits also apply. Wait until the next
minute before retrying a source-session rate-limit refusal. See the
Calls guide.
For call.ended, SDKs expose from as nullable. It is null when
reason is pod_lost, because the lost media host cannot supply an
authoritative remote-party identity.
Regenerate Platform API clients
The Platform API now publishes dot-free REST operation identifiers instead of the former internal action identifiers. If you generated a private client from an older Platform OpenAPI document, regenerate it from the latest contract and compile your integration before deploying it. HTTP methods and paths did not change, so match any hand-written wrapper by its HTTP method and path while updating the generated method call. Polymorfa does not retain aliases for the removed identifiers. The testing-numbercountry enum now contains all 243 WhatsApp-supported ISO
alpha-2 codes instead of four regional examples. Regenerate a private Platform
client so its generated country type matches the expanded request schema.
The Platform contract also includes Customer resources and Customer ownership
on session rows. Regenerate a private Platform client to receive the
customers:read and customers:manage operations, the optional
customerId testing-number field, and the nullable customer projection on
session responses. This does not change the SDK release status above.
Customers
Install the TypeScript server SDK from its development branch:Client.customers covers status and enablement, Customer records,
assigned Numbers, recent events, pairing links, and Number transfers.
externalCustomerId; a phone number belongs to a Number
or a pairing invitation, not to the Customer profile.
The URL is present only on the first successful create response. An idempotent
replay returns url: null. customers.list() keeps cursor state under
response.data.page.
Install the private CLI development branch when you need the same workflow in
a terminal:
--yes is present.
Channel deletion
No published Polymorfa SDK exposes channel deletion yet. Use a directDELETE /messaging/{session}/channels/{id} request. The call is synchronous and
confirms with { "success": true, "data": { "status": "DELETED" } } rather
than a bare success envelope, so a generated client must read data.status
instead of treating the response as empty.
If you generate a private client from the Messaging API OpenAPI document, the
operation ID is deleteChannel. Handle 400 for a malformed or non-channel
identifier and 502 for a deletion WhatsApp rejected or could not complete;
neither carries upstream error text.
Presence observation
No published Polymorfa SDK exposes presence observation yet. Use direct HTTPS requests. The modes, scopes, and per-session bounds are documented in Linked-device controls. The observation-policy operations and the presence operations take different credentials:
A project credential works across the whole presence surface: the operations
that set a policy and the operations that policy governs.
Client tokens do not use these scopes. A client token carries an empty scope
mask and is authorized only by the allowed actions recorded on it, so grant the
action rather than the scope:
A client token without the matching action receives
403 no matter which
scopes the organization credential that minted it holds. Client tokens cannot
call the observation-policy operations or set the session’s own presence.
Use a Polymorfa conversation ID or an E.164 phone number for the chat identifier.
Percent-encode path parameters, including the leading + in phone numbers.
Raw WhatsApp JIDs and LIDs are not public conversation identifiers. Encoded
path separators %2F and %252F are rejected rather than decoded into
a segment boundary, so a client token cannot reach a route its recorded action
does not cover.
If you generate a private client from the Messaging API OpenAPI document, the
operation IDs are getProjectObservationPolicy,
updateProjectObservationPolicy, getSessionObservationPolicy,
updateSessionObservationPolicy, getPresence, setPresence,
getChatPresence, and subscribePresence.
Regenerate clients for the presence types
@polymorfa/types splits the presence contract into two interfaces. The
change is not a field rename: each interface now describes a different thing,
so regenerate any client built against the previous shape.
PresenceDatais now only the session’s own presence, returned byGET /messaging/{session}/presence. It carriesdesired,desiredAt,lastSent,lastSentAt, andauthoritative, which is alwaysfalsebecause the linked-device protocol has no synchronous server read of the current session presence. Its previousavailableandlastSeenfields are gone.- Contact and chat observation is now
ChatPresenceData, returned byGET /messaging/{session}/presence/{chatId}. Readstatusfirst:unknown,fresh, orstale, withunknownReasongivingdisabled,not_observed, orsuspended.availableandlastSeenare optional here and are absent for a contact the policy did not observe, so code that treatedavailableas always present must handleundefined. lastSeenis an ISO 8601 timestamp string onChatPresenceData. It was a Unix timestamp in seconds onPresenceData. Arithmetic on the old numeric value must be replaced with date parsing.ChatPresenceDatano longer carriescomposingandpausedparticipant arrays. A single optionalchatStateobject reportssender,state, optionalmedia,observedAt, andstale.ChatPresenceDataaddspolicyandtypingPolicy, bothObservationMode(off,events, orcache), reporting the effective policy that produced the response, alongsidetypingStatus,typingUnknownReason,stale, andsubscriptionExpiresAt.
id as the stable Polymorfa user key. It does not contain a WhatsApp LID.
The optional phoneNumber, bsuid, and username fields are aliases and
must not be used as independent contact keys. See User identities
for lookup and upsert guidance.
No published Polymorfa SDK exposes the identity verification operation yet.
Use the direct Messaging API endpoint documented in User identities.
The response contains the 60-digit code and base64 display-QR payload for an
Polymorfa user ID; the verification-key payload is not part of the public response.
WhatsApp Business App commerce
No published Polymorfa SDK exposes catalog, product, collection, or order methods yet. Use direct HTTPS requests for these operations and grant the calling organization credential thebusiness:read scope. Request bounds and
resource workflows are documented in
Catalogs and commerce.
If you generate a private client from the Messaging API OpenAPI document, use
the getBusinessCatalog, getBusinessProduct, getBusinessCollections,
getBusinessCollection, and getBusinessOrder operation IDs. Keep order
lookup tokens in the POST body.
BanSafe
No published Polymorfa SDK exposes BanSafe yet. Use direct HTTPS requests. The scores, findings, restrictions, and privacy boundary are documented in BanSafe. If you generate a private client from the Platform API OpenAPI document, the BanSafe operation IDs arelistBanSafeHealth, getBanSafeHealth,
listBanSafeHealthHistory, listBanSafeFindings, acknowledgeBanSafeFinding,
listBanSafeSignals, getBanSafeTelemetry, listBanSafeTelemetryHistory,
listBanSafeCollection, listBanSafeHealthActions,
listBanSafeEnforcement, appealBanSafeEnforcement, listBanSafeIncidents,
createBanSafeIncident, retractBanSafeIncident,
listBanSafeClaims, getBanSafeClaim, getProjectWarmupPlanSettings,
updateProjectWarmupPlanSettings, getInsuranceEvidenceSettings, and
updateInsuranceEvidenceSettings. They add the request and response types
BanSafeNumber, BanSafeNumberDetail, BanSafeNumberWarmup, BanSafeFinding,
BanSafeHealthProbabilities, BanSafeObservedAccountState, BanSafeNumberEnforcement,
BanSafeHealthHistory, BanSafeHealthPoint, BanSafeFindingAcknowledgement,
BanSafeSignalDefinition, BanSafeSignalCodeCount, BanSafeSignal,
BanSafeCollectionStatus, BanSafeTelemetrySnapshot,
BanSafeCollectionSession, BanSafeTelemetryDetail, BanSafeHealthAction,
BanSafeEnforcementSummary, BanSafeAppealReceipt, BanSafeIncident,
BanSafeIncidentReceipt, BanSafeClaim,
BanSafeClaimEvidence, ProjectWarmupPlan, WarmupPlanSettings,
WarmupCurvePoint, UpdateProjectWarmupPlanInput, ProjectInsuranceEvidence,
UpdateProjectInsuranceEvidenceInput,
AcknowledgeBanSafeFindingInput, AppealBanSafeEnforcementInput, and
ReportBanSafeIncidentInput.
acknowledgeBanSafeFinding and appealBanSafeEnforcement carry no
x-required-scope and accept only a signed-in Console session, so leave them
out of a client built for an organization key or a project token.
retractBanSafeIncident takes sessions:manage like createBanSafeIncident.
The five telemetry, collection, and Health-action inspection methods take
sessions:read. Their paginated methods preserve the response page object;
the cursors are opaque and cannot be reconstructed from the final row.
Safe Mode, the warm-up plan, and insurance evidence are each on both documents
under different operation IDs, so a client generated from both gets two names
for one surface.
Both documents define
ProjectSafeMode, SessionSafeMode, and
ProjectWarmupPlan; each setting on SessionSafeMode additionally accepts
inherit. The Platform document additionally defines SafeModeSettings,
SafeModeOverride, SafeModeApplied, UpdateProjectSafeModeInput,
UpdateSessionSafeModeInput, WarmupPlanSettings, WarmupCurvePoint, and
UpdateProjectWarmupPlanInput. Both documents type insurance evidence as ProjectInsuranceEvidence. The
Platform write body uses UpdateProjectInsuranceEvidenceInput, with a required
boolean enabled. A write can return 503 propagation_pending after storing
the setting if a connected number has not confirmed it.
A generated client must preserve nullable Health fields. health is null
without a supported estimate or enough fresh evidence. Do not render null as
zero: zero is the lowest valid estimate. Read healthSource,
healthEstimatorVersion, healthUnavailableReason, healthFeatureCoverage,
healthEvaluatedAt, and healthExplanation before presenting availability,
freshness, or deductions. Rules-v1 estimates have null model probabilities.
Telemetry signals also preserve nullability. measured: false carries null
value, sampleSize, and codes; a numeric zero remains a measured value.
BanSafeHealthAction.outcome uses the closed public outcome vocabulary and
does not carry worker retry or lease state.
BanSafeClaimEvidence.attributionRuleVersion is also nullable. A number names
the attribution rules used when the claim was filed; null identifies a claim
filed before Polymorfa recorded rule versions. Do not replace null with the
latest version.
BanSafeNumberDetail.warmup reports enabled, tenureDay, nullable tenureSource
(history, link, or plan), and nullable
allowance, sentToday, and resetsAt, plus the projected curve. A null
tenureSource means the source is unverified; plan identifies the plan-start
fallback, not a verified number age. Health history contains accepted
evaluations only. Warm-up allowance and send counts remain on the current
number detail. BanSafeIncident includes
nullable closedAt, closedBy, and claimId. The withdrawal operation takes
no request body and returns that incident type, with documented 400, 404, and
409 failures.
Error bodies on these operations carry the same four fields on both documents:
error, and optionally code, docs, and retryAfter. Only error is
always present. Regenerate any client whose error type was pinned to
{ error, docs }; the added fields are optional, so a client that ignores them
keeps working. See Errors.
Daily allowance sends can return 429 bansafe_daily_allowance_reached,
503 bansafe_accounting_unavailable, or 409 bansafe_send_outcome_unknown.
The first two carry retryAfter; never automatically retry an unknown outcome.
The five public BanSafe webhook payload types are BanSafeHealthThresholdPayload, BanSafeEnforcementPayload, BanSafeActionPayload, BanSafeIncidentPayload, and BanSafeClaimPayload.
Also, MessageFailedPayload includes the blocked_by_safety error class,
optional code, and optional retryAfter. See
Webhooks.
These additions do not change the SDK release status above.
History sync configuration
When creating or updating a linked-device session directly, clients may sendhistorySync with mode set to metadata_only or deliver and
requestFull set to a boolean. Generated clients must treat this field as a
session configuration object, not an opaque message payload.
Generated clients for the native Messaging API expose business profile fields
such as description, websites, and coverPhotoId, plus typed profile and
cover-photo update requests. They also expose the catalog product mutation
request, image-source union, compliance fields, and delete result. The 5 MiB
cover and 16 MiB product-image limits apply to decoded image bytes. This does
not change the SDK release status above. Generated clients also expose typed
collection create and partial-update requests, collection mutation results,
and zero-based collection reorder moves. Direct HTTPS requests remain the
supported integration path.
Generated clients also expose typed cart settings, product visibility changes,
and product or collection appeal requests. Catalog creation has no request
body. These additions do not change the SDK release status above.
Generated clients also expose the complete merchant-compliance record used by
the live read and replacement operations, including legal entity type,
customer-care details, and grievance officer details. These additions do not
change the SDK release status above.
Generated clients also expose create, complete-replacement, and delete
operations for WhatsApp Business App quick replies. They also expose the
best-effort list response and quickReplyMode observation-policy field.
events retains no content, cache keeps a bounded in-memory projection, and
off disables observation. These additions do not change the SDK release
status above.
Generated clients also expose live Business App linked-account and feature
eligibility reads. Linked-account responses omit embedded profile-picture
bytes and return URL metadata. These additions do not change the SDK release
status above.
Generated Messaging API clients also expose typed addressMessage and flow
send payloads and the nativeFlowResponse webhook object. The flow payload
references a published Flow; Flow creation and publishing are separate from
message sending. These additions do not change the SDK release status above.
Browser call integrations receive participant joins, state changes, and departures
through the call lifecycle connection. connectEvents() consumers can subscribe
to participantJoined, participantState, and participantLeft. Changes missed
during a disconnect are not replayed. Participant mute and video fields remain
reserved and report false.
Feature availability
The feature availability endpoint accepts authenticated HTTP requests. Use HTTP when your installed SDK has no matching method.Cloud connections through QuickLink
Use QuickLink to connect customer-owned Cloud API or linked-device numbers. Link configuration separatesconnectionPreference
(cloud, linked, both) from connectionEnforcement (prefer, force).
Use the HTTP API when your installed SDK does not expose these fields; this
contract does not imply that a new SDK release has been published.
Cloud history webhooks use a JSON kind and value payload. Consumers of
history.sync must distinguish it from linked-device compressed chunks.
Subscribe to contact.sync and message.echo for contact synchronization and
Business app messages.
QuickLink creation accepts an optional externalId for your own correlation and
a safe per-link settings overlay.
The reference is returned on the resulting session and native session lifecycle
webhooks. Set success and failure callback URLs in the project’s QuickLink
settings or override them for one link under settings. Check your installed SDK
types before using these fields, or use the HTTP contract.
Meta Cloud API onboarding methods require team beta access and an active
project. An installed SDK method does not enable onboarding. See QuickLink
for unavailable choices, withdrawal and pending-operation behavior.
Test-number operations require the team’s beta enrollment, including calls made
through an SDK. A client method does not grant access. See
Sandbox access before creating or using simulated numbers.