Data Models

Complete reference for all data structures used in the Sent API v3. All API responses follow a consistent JSON envelope format with standardized property naming conventions.

Naming Convention: The API v3 uses snake_case for all JSON property names (e.g., phone_number, created_at).


Response Envelope

All API responses follow a consistent envelope structure:

ApiResponse<T>

FieldTypeDescription
successbooleanIndicates whether the request was successful
dataT | nullThe response data (null if error)
errorApiError | nullError details (null if successful)
metaApiMetaMetadata about the request and response

Example Success Response

{
  "success": true,
  "data": {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "phone_number": "+1234567890",
    "created_at": "2024-01-15T10:30:00Z"
  },
  "error": null,
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2024-01-15T10:30:00Z",
    "version": "v3",
    "response_time_ms": 45
  }
}

Example Error Response

{
  "success": false,
  "data": null,
  "error": {
    "code": "RESOURCE_001",
    "message": "Contact not found",
    "details": null,
    "doc_url": "https://docs.sent.dm/errors/RESOURCE_001"
  },
  "meta": {
    "request_id": "req_def456",
    "timestamp": "2024-01-15T10:30:00Z",
    "version": "v3"
  }
}

Type Definitions

export interface ApiResponse<T> {
  success: boolean;
  data: T | null;
  error: ApiError | null;
  meta: ApiMeta;
}

export interface ApiError {
  code: string;
  message: string;
  details: Record<string, string[]> | null;
  doc_url: string | null;
}

export interface ApiMeta {
  request_id: string;
  timestamp: string;
  version: string;
  response_time_ms?: number;
}

export interface PaginationMeta {
  has_next_page: boolean;
  has_previous_page: boolean;
  next_cursor: string | null;
  previous_cursor: string | null;
  total_count?: number;
}
from typing import Generic, TypeVar, Optional, Dict, List, Any
from dataclasses import dataclass

T = TypeVar('T')

@dataclass
class ApiResponse(Generic[T]):
    success: bool
    data: Optional[T]
    error: Optional['ApiError']
    meta: 'ApiMeta'

@dataclass
class ApiError:
    code: str
    message: str
    details: Optional[Dict[str, List[str]]]
    doc_url: Optional[str]

@dataclass
class ApiMeta:
    request_id: str
    timestamp: str
    version: str
    response_time_ms: Optional[int] = None

@dataclass
class PaginationMeta:
    has_next_page: bool
    has_previous_page: bool
    next_cursor: Optional[str]
    previous_cursor: Optional[str]
    total_count: Optional[int] = None
package sent

// ApiResponse represents the standard API response envelope
type ApiResponse[T any] struct {
	Success bool      `json:"success"`
	Data    T         `json:"data"`
	Error   *ApiError `json:"error"`
	Meta    ApiMeta   `json:"meta"`
}

// ApiError represents error details in API responses
type ApiError struct {
	Code    string              `json:"code"`
	Message string              `json:"message"`
	Details map[string][]string `json:"details"`
	DocURL  string              `json:"doc_url"`
}

// ApiMeta contains metadata about the API request/response
type ApiMeta struct {
	RequestID      string `json:"request_id"`
	Timestamp      string `json:"timestamp"`
	Version        string `json:"version"`
	ResponseTimeMs int    `json:"response_time_ms,omitempty"`
}

// PaginationMeta contains pagination information for list responses
type PaginationMeta struct {
	HasNextPage     bool   `json:"has_next_page"`
	HasPreviousPage bool   `json:"has_previous_page"`
	NextCursor      string `json:"next_cursor"`
	PreviousCursor  string `json:"previous_cursor"`
	TotalCount      int    `json:"total_count,omitempty"`
}

Contact Models

ContactResponse

A contact represents a phone number with validated formats and available messaging channels.

FieldTypeDescription
idstring (uuid)Unique identifier for the contact
phone_numberstringPhone number in original format
format_e164stringPhone number in E.164 format (e.g., +1234567890)
format_internationalstringInternational format (e.g., +1 234-567-890)
format_nationalstringNational format (e.g., (234) 567-890)
format_rfcstringRFC 3966 format (e.g., tel:+1-234-567-890)
country_codestringCountry calling code (e.g., 1 for US/Canada)
region_codestringISO 3166-1 alpha-2 country code (e.g., US, CA)
available_channelsstringComma-separated list (e.g., sms,whatsapp)
default_channelstringDefault messaging channel (sms or whatsapp)
opt_outbooleanWhether the contact has opted out of messaging
created_atstring (date-time)When the contact was created
updated_atstring (date-time)When the contact was last updated

Type Definitions

export interface Contact {
  id: string;
  phone_number: string;
  format_e164: string;
  format_international: string;
  format_national: string;
  format_rfc: string;
  country_code: string;
  region_code: string;
  available_channels: string;
  default_channel: string;
  opt_out: boolean;
  created_at: string;
  updated_at: string;
}

export interface CreateContactRequest {
  phone_number: string;
  test_mode?: boolean;
}

export interface UpdateContactRequest {
  phone_number?: string;
  test_mode?: boolean;
}
from dataclasses import dataclass
from typing import Optional

@dataclass
class Contact:
    id: str
    phone_number: str
    format_e164: str
    format_international: str
    format_national: str
    format_rfc: str
    country_code: str
    region_code: str
    available_channels: str
    default_channel: str
    opt_out: bool
    created_at: str
    updated_at: str

@dataclass
class CreateContactRequest:
    phone_number: str
    test_mode: Optional[bool] = None

@dataclass
class UpdateContactRequest:
    phone_number: Optional[str] = None
    test_mode: Optional[bool] = None
// Contact represents a phone number with validated formats and available messaging channels
type Contact struct {
	ID                  string `json:"id"`
	PhoneNumber         string `json:"phone_number"`
	FormatE164          string `json:"format_e164"`
	FormatInternational string `json:"format_international"`
	FormatNational      string `json:"format_national"`
	FormatRFC           string `json:"format_rfc"`
	CountryCode         string `json:"country_code"`
	RegionCode          string `json:"region_code"`
	AvailableChannels   string `json:"available_channels"`
	DefaultChannel      string `json:"default_channel"`
	OptOut              bool   `json:"opt_out"`
	CreatedAt           string `json:"created_at"`
	UpdatedAt           string `json:"updated_at"`
}

// CreateContactRequest represents the request body for creating a contact
type CreateContactRequest struct {
	PhoneNumber string `json:"phone_number"`
	TestMode    bool   `json:"test_mode,omitempty"`
}

// UpdateContactRequest represents the request body for updating a contact
type UpdateContactRequest struct {
	PhoneNumber string `json:"phone_number,omitempty"`
	TestMode    bool   `json:"test_mode,omitempty"`
}

Message Models

MessageResponse

A message represents an outbound message sent to a contact.

FieldTypeDescription
idstring (uuid)Unique message identifier
customer_idstring (uuid)Customer who sent the message
contact_idstring (uuid)Contact who received the message
phonestringRecipient phone number
phone_internationalstringInternational format phone number
region_codestringCountry code (e.g., US)
template_idstring (uuid) | nullTemplate used (if any)
template_namestringName of the template used
template_categorystringCategory of the template
channelstringChannel used (sms, whatsapp)
message_bodyMessageBody | nullRendered message content
statusstringMessage status (e.g., pending, sent, delivered, failed)
created_atstring (date-time)When the message was created
pricenumber | nullPrice charged for the message
eventsMessageEvent[] | nullDelivery events

Type Definitions

export interface Message {
  id: string;
  customer_id: string;
  contact_id: string;
  phone: string;
  phone_international: string;
  region_code: string;
  template_id: string | null;
  template_name: string;
  template_category: string;
  channel: string;
  message_body: MessageBody | null;
  status: MessageStatus;
  created_at: string;
  price: number | null;
  events: MessageEvent[] | null;
}

export interface MessageBody {
  body: string;
  header?: MessageHeader;
  footer?: MessageFooter;
  buttons?: MessageButton[];
}

export interface MessageHeader {
  type: 'TEXT' | 'IMAGE' | 'VIDEO' | 'DOCUMENT';
  content: string;
}

export interface MessageFooter {
  content: string;
}

export interface MessageButton {
  type: 'QUICK_REPLY' | 'URL' | 'PHONE_NUMBER';
  text: string;
  url?: string;
  phone_number?: string;
}

export interface MessageEvent {
  status: string;
  timestamp: string;
  provider: string;
  error_code?: string;
  error_message?: string;
}

export interface SendMessageRequest {
  phone_number: string;
  template_id: string;
  variables?: Record<string, string>;
  channel?: 'sms' | 'whatsapp';
  webhook_url?: string;
  callback_url?: string;
  test_mode?: boolean;
}

export type MessageStatus =
  | 'pending'
  | 'sent'
  | 'delivered'
  | 'read'
  | 'failed';
from dataclasses import dataclass
from typing import Optional, List, Dict, Literal

@dataclass
class Message:
    id: str
    customer_id: str
    contact_id: str
    phone: str
    phone_international: str
    region_code: str
    template_id: Optional[str]
    template_name: str
    template_category: str
    channel: str
    message_body: Optional['MessageBody']
    status: str
    created_at: str
    price: Optional[float]
    events: Optional[List['MessageEvent']]

@dataclass
class MessageBody:
    body: str
    header: Optional['MessageHeader'] = None
    footer: Optional['MessageFooter'] = None
    buttons: Optional[List['MessageButton']] = None

@dataclass
class MessageHeader:
    type: Literal['TEXT', 'IMAGE', 'VIDEO', 'DOCUMENT']
    content: str

@dataclass
class MessageFooter:
    content: str

@dataclass
class MessageButton:
    type: Literal['QUICK_REPLY', 'URL', 'PHONE_NUMBER']
    text: str
    url: Optional[str] = None
    phone_number: Optional[str] = None

@dataclass
class MessageEvent:
    status: str
    timestamp: str
    provider: str
    error_code: Optional[str] = None
    error_message: Optional[str] = None

@dataclass
class SendMessageRequest:
    phone_number: str
    template_id: str
    variables: Optional[Dict[str, str]] = None
    channel: Optional[Literal['sms', 'whatsapp']] = None
    webhook_url: Optional[str] = None
    callback_url: Optional[str] = None
    test_mode: Optional[bool] = None
// Message represents an outbound message sent to a contact
type Message struct {
	ID                 string          `json:"id"`
	CustomerID         string          `json:"customer_id"`
	ContactID          string          `json:"contact_id"`
	Phone              string          `json:"phone"`
	PhoneInternational string          `json:"phone_international"`
	RegionCode         string          `json:"region_code"`
	TemplateID         string          `json:"template_id"`
	TemplateName       string          `json:"template_name"`
	TemplateCategory   string          `json:"template_category"`
	Channel            string          `json:"channel"`
	MessageBody        *MessageBody    `json:"message_body"`
	Status             MessageStatus   `json:"status"`
	CreatedAt          string          `json:"created_at"`
	Price              float64         `json:"price"`
	Events             []MessageEvent  `json:"events"`
}

// MessageStatus represents the status of a message
type MessageStatus string

const (
	MessageStatusPending    MessageStatus = "pending"
	MessageStatusSent       MessageStatus = "sent"
	MessageStatusDelivered  MessageStatus = "delivered"
	MessageStatusRead       MessageStatus = "read"
	MessageStatusFailed     MessageStatus = "failed"
)

// MessageBody represents the rendered message content
type MessageBody struct {
	Body    string           `json:"body"`
	Header  *MessageHeader   `json:"header,omitempty"`
	Footer  *MessageFooter   `json:"footer,omitempty"`
	Buttons []MessageButton  `json:"buttons,omitempty"`
}

// MessageHeader represents the header of a message
type MessageHeader struct {
	Type    string `json:"type"` // TEXT, IMAGE, VIDEO, DOCUMENT
	Content string `json:"content"`
}

// MessageFooter represents the footer of a message
type MessageFooter struct {
	Content string `json:"content"`
}

// MessageButton represents a button in a message
type MessageButton struct {
	Type        string `json:"type"` // QUICK_REPLY, URL, PHONE_NUMBER
	Text        string `json:"text"`
	URL         string `json:"url,omitempty"`
	PhoneNumber string `json:"phone_number,omitempty"`
}

// MessageEvent represents a delivery event for a message
type MessageEvent struct {
	Status       string `json:"status"`
	Timestamp    string `json:"timestamp"`
	Provider     string `json:"provider"`
	ErrorCode    string `json:"error_code,omitempty"`
	ErrorMessage string `json:"error_message,omitempty"`
}

// SendMessageRequest represents the request body for sending a message
type SendMessageRequest struct {
	PhoneNumber string            `json:"phone_number"`
	TemplateID  string            `json:"template_id"`
	Variables   map[string]string `json:"variables,omitempty"`
	Channel     string            `json:"channel,omitempty"` // sms, whatsapp
	WebhookURL  string            `json:"webhook_url,omitempty"`
	CallbackURL string            `json:"callback_url,omitempty"`
	TestMode    bool              `json:"test_mode,omitempty"`
}

Template Models

TemplateResponse

A template is a reusable message format with variables for personalization.

FieldTypeDescription
idstring (uuid)Unique template identifier
namestringTemplate display name
categorystringTemplate category: MARKETING, UTILITY, AUTHENTICATION
languagestringLanguage code (e.g., en_US)
statusstringApproval status: APPROVED, PENDING, REJECTED
channelsstring[]Supported channels (sms, whatsapp)
variablesstring[]Template variable names
created_atstring (date-time)When the template was created
updated_atstring (date-time) | nullWhen the template was last updated
is_publishedbooleanWhether the template is published and active

Type Definitions

export interface Template {
  id: string;
  name: string;
  category: TemplateCategory;
  language: string;
  status: TemplateStatus;
  channels: string[];
  variables: string[];
  created_at: string;
  updated_at: string | null;
  is_published: boolean;
}

export interface TemplateBody {
  content: string;
  variables?: TemplateVariable[];
}

export interface TemplateHeader {
  type: 'TEXT' | 'IMAGE' | 'VIDEO' | 'DOCUMENT';
  content: string;
}

export interface TemplateFooter {
  content: string;
}

export interface TemplateButton {
  type: 'QUICK_REPLY' | 'URL' | 'PHONE_NUMBER';
  text: string;
  url?: string;
  phone_number?: string;
}

export interface TemplateVariable {
  name: string;
  type: 'text' | 'number' | 'date';
  example?: string;
}

export interface CreateTemplateRequest {
  name: string;
  category: TemplateCategory;
  language: string;
  body: TemplateBody;
  header?: TemplateHeader;
  footer?: TemplateFooter;
  buttons?: TemplateButton[];
  channels?: string[];
  test_mode?: boolean;
}

export interface UpdateTemplateRequest {
  name?: string;
  category?: TemplateCategory;
  body?: TemplateBody;
  test_mode?: boolean;
}

export type TemplateCategory = 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';
export type TemplateStatus = 'APPROVED' | 'PENDING' | 'REJECTED';
from dataclasses import dataclass
from typing import Optional, List, Literal

@dataclass
class Template:
    id: str
    name: str
    category: str
    language: str
    status: str
    channels: List[str]
    variables: List[str]
    created_at: str
    updated_at: Optional[str]
    is_published: bool

@dataclass
class TemplateBody:
    content: str
    variables: Optional[List['TemplateVariable']] = None

@dataclass
class TemplateHeader:
    type: Literal['TEXT', 'IMAGE', 'VIDEO', 'DOCUMENT']
    content: str

@dataclass
class TemplateFooter:
    content: str

@dataclass
class TemplateButton:
    type: Literal['QUICK_REPLY', 'URL', 'PHONE_NUMBER']
    text: str
    url: Optional[str] = None
    phone_number: Optional[str] = None

@dataclass
class TemplateVariable:
    name: str
    type: Literal['text', 'number', 'date']
    example: Optional[str] = None

@dataclass
class CreateTemplateRequest:
    name: str
    category: str
    language: str
    body: TemplateBody
    header: Optional[TemplateHeader] = None
    footer: Optional[TemplateFooter] = None
    buttons: Optional[List[TemplateButton]] = None
    channels: Optional[List[str]] = None
    test_mode: Optional[bool] = None

@dataclass
class UpdateTemplateRequest:
    name: Optional[str] = None
    category: Optional[str] = None
    body: Optional[TemplateBody] = None
    test_mode: Optional[bool] = None
// Template represents a reusable message format with variables for personalization
type Template struct {
	ID          string   `json:"id"`
	Name        string   `json:"name"`
	Category    TemplateCategory `json:"category"`
	Language    string   `json:"language"`
	Status      TemplateStatus   `json:"status"`
	Channels    []string `json:"channels"`
	Variables   []string `json:"variables"`
	CreatedAt   string   `json:"created_at"`
	UpdatedAt   string   `json:"updated_at"`
	IsPublished bool     `json:"is_published"`
}

// TemplateCategory represents the category of a template
type TemplateCategory string

const (
	TemplateCategoryMarketing      TemplateCategory = "MARKETING"
	TemplateCategoryUtility        TemplateCategory = "UTILITY"
	TemplateCategoryAuthentication TemplateCategory = "AUTHENTICATION"
)

// TemplateStatus represents the approval status of a template
type TemplateStatus string

const (
	TemplateStatusApproved  TemplateStatus = "APPROVED"
	TemplateStatusPending   TemplateStatus = "PENDING"
	TemplateStatusRejected  TemplateStatus = "REJECTED"
)

// TemplateBody represents the body of a template
type TemplateBody struct {
	Content   string             `json:"content"`
	Variables []TemplateVariable `json:"variables,omitempty"`
}

// TemplateHeader represents the header of a template
type TemplateHeader struct {
	Type    string `json:"type"` // TEXT, IMAGE, VIDEO, DOCUMENT
	Content string `json:"content"`
}

// TemplateFooter represents the footer of a template
type TemplateFooter struct {
	Content string `json:"content"`
}

// TemplateButton represents a button in a template
type TemplateButton struct {
	Type        string `json:"type"` // QUICK_REPLY, URL, PHONE_NUMBER
	Text        string `json:"text"`
	URL         string `json:"url,omitempty"`
	PhoneNumber string `json:"phone_number,omitempty"`
}

// TemplateVariable represents a variable in a template
type TemplateVariable struct {
	Name    string `json:"name"`
	Type    string `json:"type"` // text, number, date
	Example string `json:"example,omitempty"`
}

// CreateTemplateRequest represents the request body for creating a template
type CreateTemplateRequest struct {
	Name     string           `json:"name"`
	Category TemplateCategory `json:"category"`
	Language string           `json:"language"`
	Body     TemplateBody     `json:"body"`
	Header   *TemplateHeader  `json:"header,omitempty"`
	Footer   *TemplateFooter  `json:"footer,omitempty"`
	Buttons  []TemplateButton `json:"buttons,omitempty"`
	Channels []string         `json:"channels,omitempty"`
	TestMode bool             `json:"test_mode,omitempty"`
}

// UpdateTemplateRequest represents the request body for updating a template
type UpdateTemplateRequest struct {
	Name     string           `json:"name,omitempty"`
	Category TemplateCategory `json:"category,omitempty"`
	Body     *TemplateBody    `json:"body,omitempty"`
	TestMode bool             `json:"test_mode,omitempty"`
}

Profile Models

ProfileResponse

A profile (sender profile) represents an organization or sub-account for sending messages.

FieldTypeDescription
idstring (uuid)Unique profile identifier
namestringProfile name
iconstring | nullProfile icon URL
descriptionstring | nullProfile description
short_namestring | nullShort name/abbreviation
rolestring | nullUser's role: admin, billing, developer
statusstring | nullSetup status: incomplete, pending_review, approved, rejected
created_atstring (date-time)When the profile was created
settingsProfileSettingsProfile configuration

Type Definitions

export interface Profile {
  id: string;
  name: string;
  icon: string | null;
  description: string | null;
  short_name: string | null;
  role: 'admin' | 'billing' | 'developer' | null;
  status: 'incomplete' | 'pending_review' | 'approved' | 'rejected' | null;
  created_at: string;
  settings: ProfileSettings;
}

export interface ProfileSettings {
  default_channel: string | null;
  webhook_url: string | null;
  timezone: string | null;
  language: string | null;
}

export interface CreateProfileRequest {
  name: string;
  description?: string;
  short_name?: string;
  test_mode?: boolean;
}
from dataclasses import dataclass
from typing import Optional, Literal

@dataclass
class Profile:
    id: str
    name: str
    icon: Optional[str]
    description: Optional[str]
    short_name: Optional[str]
    role: Optional[Literal['admin', 'billing', 'developer']]
    status: Optional[Literal['incomplete', 'pending_review', 'approved', 'rejected']]
    created_at: str
    settings: 'ProfileSettings'

@dataclass
class ProfileSettings:
    default_channel: Optional[str]
    webhook_url: Optional[str]
    timezone: Optional[str]
    language: Optional[str]

@dataclass
class CreateProfileRequest:
    name: str
    description: Optional[str] = None
    short_name: Optional[str] = None
    test_mode: Optional[bool] = None
// Profile represents a sender profile for sending messages
type Profile struct {
	ID          string          `json:"id"`
	Name        string          `json:"name"`
	Icon        string          `json:"icon"`
	Description string          `json:"description"`
	ShortName   string          `json:"short_name"`
	Role        ProfileRole     `json:"role"`
	Status      ProfileStatus   `json:"status"`
	CreatedAt   string          `json:"created_at"`
	Settings    ProfileSettings `json:"settings"`
}

// ProfileRole represents the user's role in a profile
type ProfileRole string

const (
	ProfileRoleAdmin     ProfileRole = "admin"
	ProfileRoleBilling   ProfileRole = "billing"
	ProfileRoleDeveloper ProfileRole = "developer"
)

// ProfileStatus represents the setup status of a profile
type ProfileStatus string

const (
	ProfileStatusIncomplete     ProfileStatus = "incomplete"
	ProfileStatusPendingReview  ProfileStatus = "pending_review"
	ProfileStatusApproved       ProfileStatus = "approved"
	ProfileStatusRejected       ProfileStatus = "rejected"
)

// ProfileSettings represents the configuration for a profile
type ProfileSettings struct {
	DefaultChannel string `json:"default_channel"`
	WebhookURL     string `json:"webhook_url"`
	Timezone       string `json:"timezone"`
	Language       string `json:"language"`
}

// CreateProfileRequest represents the request body for creating a profile
type CreateProfileRequest struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	ShortName   string `json:"short_name,omitempty"`
	TestMode    bool   `json:"test_mode,omitempty"`
}

Webhook Models

WebhookV3Response

A webhook endpoint receives event notifications for message delivery and other events.

FieldTypeDescription
idstring (uuid)Unique webhook identifier
urlstringWebhook endpoint URL
descriptionstring | nullWebhook description
event_typesstring[]Subscribed event types
is_activebooleanWhether the webhook is active
signing_secretstring | nullSecret for verifying webhook signatures
created_atstring (date-time)When the webhook was created
updated_atstring (date-time) | nullWhen the webhook was last updated

Type Definitions

export interface Webhook {
  id: string;
  url: string;
  description: string | null;
  event_types: string[];
  is_active: boolean;
  signing_secret: string | null;
  created_at: string;
  updated_at: string | null;
}

export interface WebhookEvent {
  id: string;
  webhook_id: string;
  event_type: string;
  payload: Record<string, unknown>;
  status: string;
  response_status_code?: number;
  created_at: string;
}

export interface WebhookEventType {
  name: string;
  description: string;
  category: string;
}

export interface CreateWebhookRequest {
  url: string;
  event_types: string[];
  description?: string;
  test_mode?: boolean;
}
from dataclasses import dataclass
from typing import Optional, List, Dict, Any

@dataclass
class Webhook:
    id: str
    url: str
    description: Optional[str]
    event_types: List[str]
    is_active: bool
    signing_secret: Optional[str]
    created_at: str
    updated_at: Optional[str]

@dataclass
class WebhookEvent:
    id: str
    webhook_id: str
    event_type: str
    payload: Dict[str, Any]
    status: str
    response_status_code: Optional[int] = None
    created_at: str

@dataclass
class WebhookEventType:
    name: str
    description: str
    category: str

@dataclass
class CreateWebhookRequest:
    url: str
    event_types: List[str]
    description: Optional[str] = None
    test_mode: Optional[bool] = None
// Webhook represents a webhook endpoint for receiving event notifications
type Webhook struct {
	ID            string   `json:"id"`
	URL           string   `json:"url"`
	Description   string   `json:"description"`
	EventTypes    []string `json:"event_types"`
	IsActive      bool     `json:"is_active"`
	SigningSecret string   `json:"signing_secret"`
	CreatedAt     string   `json:"created_at"`
	UpdatedAt     string   `json:"updated_at"`
}

// WebhookEvent represents a single webhook delivery attempt
type WebhookEvent struct {
	ID                 string                 `json:"id"`
	WebhookID          string                 `json:"webhook_id"`
	EventType          string                 `json:"event_type"`
	Payload            map[string]interface{} `json:"payload"`
	Status             string                 `json:"status"`
	ResponseStatusCode int                    `json:"response_status_code,omitempty"`
	CreatedAt          string                 `json:"created_at"`
}

// WebhookEventType represents an available webhook event type
type WebhookEventType struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Category    string `json:"category"`
}

// CreateWebhookRequest represents the request body for creating a webhook
type CreateWebhookRequest struct {
	URL         string   `json:"url"`
	EventTypes  []string `json:"event_types"`
	Description string   `json:"description,omitempty"`
	TestMode    bool     `json:"test_mode,omitempty"`
}

On this page