Contacts

A contact in Sent is a validated communication endpoint: a phone number enriched with the channel information the platform needs to reach its owner.

Rather than forcing developers to manage the complexity of different messaging channels, contacts provide a unified abstraction that handles channel validation, metadata, and routing automatically.

Contacts Architecture

The Sent Contacts Architecture is designed to be intelligent and flexible, while allowing you to have full control over the messaging experience.

Channel-Agnostic Abstraction

Traditional messaging platforms require developers to understand and integrate with separate APIs for SMS, WhatsApp, and other channels. This leads to several problems such as integration complexity, validation overhead, routing decisions, and fallback handling, all of which need to be implemented manually.

Sent solves these problems by providing a channel-agnostic abstraction. When you send a message to a contact, the platform handles all channel-specific complexity behind a unified interface.

The Contact as a Validated Communication Endpoint

A contact in Sent is fundamentally different from a simple phone number or user record. It represents:

A validated, intelligent communication endpoint that:

  • Knows which messaging channels can successfully reach the recipient
  • Understands the optimal channel for delivery based on regional preferences and availability
  • Maintains channel-specific formatting and validation rules
  • Provides automatic fallback routing when primary channels fail

This abstraction allows developers to focus on their app logic rather than the intricacies of multi-channel messaging infrastructure.

Channel Availability and Routing

A contact records which channels can currently reach its phone number. SMS, WhatsApp, and RCS are all live channels in Sent, and a contact carries a per-channel availability record for each.

When you send without pinning a channel, routing selects among the contact's available channels per recipient at send time. There is no fixed channel preference order: the winning route depends on the routing rules configured for your account and the recipient, and the remaining candidates are kept as fallbacks. The factors the router weighs are summarized in Routing Factors; Unified Messaging Intelligence explains the decision engine, and the channel routing reference specifies the exact matching and ordering rules.

Persistent State

Contacts maintain persistent state that benefits future interactions:

  • Channel availability is cached and periodically refreshed
  • Routing decisions improve based on delivery history
  • Validation status prevents repeated failed delivery attempts

This persistence means that applications naturally become more efficient over time without additional developer effort.

Phone Number Normalization

Contacts handle the complexity of phone number formatting across different contexts:

  • E.164 format: International standard for programmatic use
  • International format: Human-readable international representation
  • National format: Localized formatting for user interfaces
  • RFC format: Standardized format for system integration

This multi-format support ensures that contacts work correctly regardless of how phone numbers are provided or displayed in your app.

Customer Scoping and Isolation

Contacts are scoped to individual customers, providing:

  • Access control: Customers can only access their own contacts
  • Billing isolation: Message costs are attributed correctly
  • Data privacy: Contact information remains segregated between customers

This architecture supports multi-tenant applications while maintaining security and billing accuracy.

Channel-Specific Metadata

While contacts abstract channel complexity, they also preserve channel-specific information when needed:

  • WhatsApp profile status: Whether a number has an active WhatsApp Business API registration
  • SMS carrier information: Network-specific delivery capabilities
  • Regional restrictions: Compliance and availability constraints by geography

This metadata enables advanced applications to make informed decisions while still benefiting from the unified API approach.

Contact Intelligence

Automatic Contact Creation

Contacts follow a lazy creation pattern that reduces integration friction. This approach means developers never need to pre-register contacts. The system creates and optimizes them automatically during the first messaging interaction.

Here's how it works:

Real-Time Channel Validation

When a contact is created, and again as messages are sent to it, Sent validates the phone number against the supported channels:

  • SMS availability: verified through carrier network validation
  • WhatsApp registration: checked against the WhatsApp Business API
  • RCS capability: checked against the recipient device's RCS support, with the result cached for reuse

This validation ensures that every contact represents a deliverable endpoint, reducing bounce rates and failed message attempts.

Contact Enrichment Over Time

Contacts become more intelligent through usage:

  • Delivery success patterns inform future routing decisions
  • Channel preferences are learned from recipient engagement
  • Validation status is periodically refreshed to maintain accuracy

This creates a feedback loop where messaging performance improves automatically as the system learns more about each contact.

Contacts for Developers

Sent supports two primary patterns for working with contacts. Both patterns use the same underlying intelligence but offer different levels of control and visibility.

Direct phone messaging (automatic contact creation):

  • Send immediately to any phone number
  • Contact created and optimized transparently
  • Ideal for one-off or ad-hoc messaging

Explicit contact management:

  • Retrieve and work with contact objects
  • Access channel availability metadata
  • Suitable for applications that need contact state awareness

Managing Contacts covers both patterns in practice.

When building with Sent's contact system, developers should shift their mental model to a contact-based approach

Avoid the traditional approach of branching on channel in your own code:

if (user.hasWhatsApp) {
    sendWhatsApp(message, user.phone);
} else {
    sendSMS(message, user.phone);
}

Prefer the contact-based approach, where the platform picks the channel:

sendMessage(message, contact);

On this page