Documentation
¶
Overview ¶
Package waga provides a Go client for interacting with the WhatsApp Gateway API.
The waga package enables Go applications to send WhatsApp messages, manage webhooks, and handle authentication with a WhatsApp Gateway service. It supports text and image messaging, message editing/deletion, webhook verification, and session management.
Quick Start ¶
To get started, create a new client and register your phone number:
client := waga.NewClient()
resp, err := client.Register(ctx, "6281234567890", "your-secret-key")
if err != nil {
log.Fatal(err)
}
Once registered, you can send messages:
msisdn := waga.FormatMSISDN("6281234567890")
msgResp, err := client.SendText(ctx, msisdn, "Hello, World!")
if err != nil {
log.Fatal(err)
}
Authentication ¶
The SDK supports two authentication methods:
1. Register a new phone number to obtain a JWT token 2. Use an existing JWT token with SetToken() or WithToken()
The client automatically stores the token returned by Register() for subsequent requests.
Message Formatting ¶
Phone numbers should be formatted as MSISDN (WhatsApp JID format). Use the helper functions FormatMSISDN() for individuals and FormatGroupID() for groups:
individual := waga.FormatMSISDN("6281234567890") // "6281234567890@s.whatsapp.net"
group := waga.FormatGroupID("1234567890") // "1234567890@g.us"
Webhooks ¶
Webhooks allow you to receive real-time notifications for incoming and outgoing messages. To handle webhooks securely, use the WebhookVerifier:
verifier := waga.NewWebhookVerifier("your-hmac-secret")
payload, err := verifier.ParseIncomingWebhook(body, signatureHeader)
if err != nil {
log.Fatal(err)
}
Configuration ¶
The client can be configured with options:
client := waga.NewClient(
waga.WithBaseURL("https://api.example.com"),
waga.WithTimeout(60*time.Second),
waga.WithToken("existing-jwt-token"),
)
Error Handling ¶
The SDK returns typed errors that can be checked using helper functions:
resp, err := client.SendText(ctx, msisdn, message)
if waga.IsUnauthorized(err) {
// Handle authentication error
} else if waga.IsRateLimited(err) {
// Handle rate limiting
}
For more examples and detailed usage, see the examples directory and README.md.
Index ¶
- Constants
- Variables
- func ComputeSignature(payload []byte, secret string) string
- func FormatGroupID(groupID string) string
- func FormatMSISDN(phoneNumber string) string
- func IsBadRequest(err error) bool
- func IsConflict(err error) bool
- func IsForbidden(err error) bool
- func IsGone(err error) bool
- func IsInternalServer(err error) bool
- func IsNotFound(err error) bool
- func IsRateLimited(err error) bool
- func IsUnauthorized(err error) bool
- func TraceIDFromContext(ctx context.Context) string
- func WithTraceID(ctx context.Context, traceID string) context.Context
- type AdminClient
- func (a *AdminClient) Live(ctx context.Context) (*HealthResponse, error)
- func (a *AdminClient) Ready(ctx context.Context) (*HealthReadyResponse, error)
- func (a *AdminClient) Session(ctx context.Context, phone string) (*AdminSessionResponse, error)
- func (a *AdminClient) Sessions(ctx context.Context) (*SessionInventory, error)
- type AdminSessionResponse
- type AvatarResponse
- type ChatPresenceRequest
- type Client
- func (c *Client) CheckContact(ctx context.Context, msisdn string) (*ContactCheckResponse, error)
- func (c *Client) CreateGroup(ctx context.Context, req CreateGroupRequest) (*CreateGroupResponse, error)
- func (c *Client) DeleteGroupPhoto(ctx context.Context, chat string) (*GroupPhotoResponse, error)
- func (c *Client) DeleteMessage(ctx context.Context, msisdn, messageID string) error
- func (c *Client) EditMessage(ctx context.Context, msisdn, messageID, newMessage string) error
- func (c *Client) GetAvatar(ctx context.Context, chat string, preview bool, priorID ...string) (*AvatarResponse, error)
- func (c *Client) GetContactInfo(ctx context.Context, chat string) (*ContactInfoResponse, error)
- func (c *Client) GetGroupInfo(ctx context.Context, chat string) (*GroupInfoResponse, error)
- func (c *Client) GetGroupInviteInfo(ctx context.Context, code string) (*GroupInfoResponse, error)
- func (c *Client) GetGroupInviteLink(ctx context.Context, chat string) (*GroupInviteLinkResponse, error)
- func (c *Client) GetIncomingMessages(ctx context.Context, limit int) (*IncomingMessagesResponse, error)
- func (c *Client) GetJobStatus(ctx context.Context, jobID string) (*JobStatusResponse, error)
- func (c *Client) GetLoginStatus(ctx context.Context) (*LoginStatus, error)
- func (c *Client) GetPairCode(ctx context.Context) (*LoginPairResponse, error)
- func (c *Client) GetQRCode(ctx context.Context, format string) (*LoginQrResponse, error)
- func (c *Client) GetToken() string
- func (c *Client) GetWebhook(ctx context.Context) (*WebhookResponse, error)
- func (c *Client) Health(ctx context.Context) (*HealthResponse, error)
- func (c *Client) JoinGroup(ctx context.Context, code string) (*JoinGroupResponse, error)
- func (c *Client) LeaveGroup(ctx context.Context, chat string) error
- func (c *Client) LinkSubGroup(ctx context.Context, chat, childJID string) error
- func (c *Client) ListCommunityParticipants(ctx context.Context, chat string) (*CommunityParticipantsResponse, error)
- func (c *Client) ListContacts(ctx context.Context, limit, offset int) (*ContactListResponse, error)
- func (c *Client) ListGroups(ctx context.Context) (*GroupListResponse, error)
- func (c *Client) ListJoinRequests(ctx context.Context, chat string) (*GroupJoinRequestsResponse, error)
- func (c *Client) ListSubGroups(ctx context.Context, chat string) (*SubGroupListResponse, error)
- func (c *Client) Logout(ctx context.Context) error
- func (c *Client) MarkRead(ctx context.Context, chat string, messageIDs []string, sender string) error
- func (c *Client) React(ctx context.Context, msisdn, messageID, emoji string, senderMsisdn ...string) error
- func (c *Client) Reconnect(ctx context.Context) error
- func (c *Client) Register(ctx context.Context, phoneNumber, secretKey string) (*RegisterResponse, error)
- func (c *Client) RegisterWebhook(ctx context.Context, url, hmacSecret string) error
- func (c *Client) ResetGroupInviteLink(ctx context.Context, chat string) (*GroupInviteLinkResponse, error)
- func (c *Client) ReviewJoinRequests(ctx context.Context, chat, action string, participants []string) (*GroupJoinRequestsActionResponse, error)
- func (c *Client) SendAudio(ctx context.Context, msisdn string, audio io.Reader, isPTT, isViewOnce bool, ...) (*SendMessageResponse, error)
- func (c *Client) SendChatPresence(ctx context.Context, chat, state string) error
- func (c *Client) SendDocument(ctx context.Context, msisdn string, document io.Reader, ...) (*SendMessageResponse, error)
- func (c *Client) SendImage(ctx context.Context, msisdn string, image io.Reader, caption string, ...) (*SendMessageResponse, error)
- func (c *Client) SendLocation(ctx context.Context, msisdn string, latitude, longitude float64, ...) (*SendMessageResponse, error)
- func (c *Client) SendPoll(ctx context.Context, msisdn, question string, options []string, ...) (*SendMessageResponse, error)
- func (c *Client) SendSticker(ctx context.Context, msisdn string, sticker io.Reader, opts ...SendOption) (*SendMessageResponse, error)
- func (c *Client) SendText(ctx context.Context, msisdn, message string, opts ...SendOption) (*SendMessageResponse, error)
- func (c *Client) SendVideo(ctx context.Context, msisdn string, video io.Reader, caption string, ...) (*SendMessageResponse, error)
- func (c *Client) SetGroupName(ctx context.Context, chat, name string) error
- func (c *Client) SetGroupPhoto(ctx context.Context, chat string, jpeg io.Reader) (*GroupPhotoResponse, error)
- func (c *Client) SetGroupSettings(ctx context.Context, chat string, announce, locked *bool) (*GroupSettingsResponse, error)
- func (c *Client) SetGroupTopic(ctx context.Context, chat, topic string) error
- func (c *Client) SetToken(token string)
- func (c *Client) UnlinkSubGroup(ctx context.Context, chat, childJID string) error
- func (c *Client) UnregisterWebhook(ctx context.Context) error
- func (c *Client) UpdateGroupParticipants(ctx context.Context, chat, action string, participants []string) (*GroupParticipantsResponse, error)
- type CommunityParticipantItem
- type CommunityParticipantsResponse
- type ContactCheckResponse
- type ContactInfoResponse
- type ContactListItem
- type ContactListResponse
- type CreateGroupRequest
- type CreateGroupResponse
- type ErrorResponse
- type GroupInfoResponse
- type GroupInviteLinkResponse
- type GroupJoinRequestItem
- type GroupJoinRequestsActionResponse
- type GroupJoinRequestsResponse
- type GroupListItem
- type GroupListResponse
- type GroupParticipantItem
- type GroupParticipantsResponse
- type GroupPhotoResponse
- type GroupSettingsResponse
- type HealthComponent
- type HealthReadyResponse
- type HealthResponse
- type IncomingEventMessage
- type IncomingMessage
- type IncomingMessageMediaInfo
- type IncomingMessageType
- type IncomingMessagesResponse
- type IncomingWebhookPayload
- type JobStatusResponse
- type JoinGroupResponse
- type LoginPairResponse
- type LoginQrResponse
- type LoginStatus
- type MarkReadRequest
- type MessageDeleteRequest
- type MessageEditRequest
- type MessageReactRequest
- type Option
- type OutgoingEventMessage
- type OutgoingWebhookPayload
- type ParticipantInvite
- type ParticipantResult
- type PresenceState
- type RegisterRequest
- type RegisterResponse
- type SDKError
- type SendLocationMessageRequest
- type SendMessageResponse
- type SendMessageTextRequest
- type SendOption
- type SendPollMessageRequest
- type SessionEvent
- type SessionInventory
- type SessionInventoryItem
- type SubGroupItem
- type SubGroupListResponse
- type SuccessResponse
- type WebhookEvent
- type WebhookEventType
- type WebhookRegisterRequest
- type WebhookResponse
- type WebhookVerifier
- func (v *WebhookVerifier) ParseIncomingWebhook(payload []byte, signature string) (*IncomingWebhookPayload, error)
- func (v *WebhookVerifier) ParseOutgoingWebhook(payload []byte, signature string) (*OutgoingWebhookPayload, error)
- func (v *WebhookVerifier) ParseWebhook(payload []byte, signature string) (*WebhookEvent, error)
- func (v *WebhookVerifier) VerifySignature(payload []byte, signatureHeader string) bool
Constants ¶
const ( // EventMessageQueued is emitted when a message is added to the queue EventMessageQueued = OutgoingEventMessageMessageQueued // EventMessageSent is emitted when a message is successfully sent EventMessageSent = OutgoingEventMessageMessageSent // EventMessageFailed is emitted when a message fails to send EventMessageFailed = OutgoingEventMessageMessageFailed // EventMessageIncoming is emitted when a message is received EventMessageIncoming = IncomingEventMessageMessageIncoming )
Outgoing event type constants for convenience
const ( // MessageTypeText represents a text message MessageTypeText = IncomingMessageTypeText // MessageTypeImage represents an image message MessageTypeImage = IncomingMessageTypeImage // MessageTypeVideo represents a video message MessageTypeVideo = IncomingMessageTypeVideo // MessageTypeAudio represents an audio message MessageTypeAudio = IncomingMessageTypeAudio // MessageTypeDocument represents a document message MessageTypeDocument = IncomingMessageTypeDocument )
Incoming message type constants for convenience
const ( // DefaultBaseURL is the default API endpoint DefaultBaseURL = "http://localhost:3000/api/v1" // DefaultAdminBaseURL is the default base URL for the admin plane. The admin // and health-probe routes live at the server ROOT, not under the /api/v1 // base path, so AdminClient defaults to the bare origin. DefaultAdminBaseURL = "http://localhost:3000" // DefaultTimeout is the default HTTP request timeout DefaultTimeout = 30 * time.Second // DefaultUserAgent is the default User-Agent header DefaultUserAgent = "WhatsApp-Gateway-SDK-Go/1.0" )
const TraceIDHeader = "X-Trace-ID"
TraceIDHeader is the HTTP header used to propagate a trace ID to the gateway. The gateway logs this ID with every operation, so requests can be correlated across your application and the gateway logs.
Variables ¶
var ( ErrUnauthorized = &SDKError{Code: http.StatusUnauthorized, Message: "unauthorized"} // ErrBadRequest is returned for invalid requests (400) ErrBadRequest = &SDKError{Code: http.StatusBadRequest, Message: "bad request"} // ErrForbidden is returned when access is denied (403) ErrForbidden = &SDKError{Code: http.StatusForbidden, Message: "forbidden"} // ErrNotFound is returned when a resource is not found (404) ErrNotFound = &SDKError{Code: http.StatusNotFound, Message: "not found"} // ErrConflict is returned for conflicting requests (409) ErrConflict = &SDKError{Code: http.StatusConflict, Message: "conflict"} // ErrGone is returned when a resource is no longer available (410), e.g. // GetGroupInviteInfo on a revoked invite link. ErrGone = &SDKError{Code: http.StatusGone, Message: "gone"} // ErrRateLimited is returned when rate limit is exceeded (429) ErrRateLimited = &SDKError{Code: http.StatusTooManyRequests, Message: "rate limited"} // ErrNotModified is returned by GetAvatar when the caller-supplied prior // avatar id (If-None-Match) still matches — the picture is unchanged (304). ErrNotModified = &SDKError{Code: http.StatusNotModified, Message: "not modified"} // ErrInternalServer is returned for server errors (500) ErrInternalServer = &SDKError{Code: http.StatusInternalServerError, Message: "internal server error"} // ErrInvalidSignature is returned when webhook signature verification fails ErrInvalidSignature = errors.New("invalid webhook signature") // ErrUnknownWebhookEvent is returned by ParseWebhook when the payload's // event field is not a recognized webhook event type. ErrUnknownWebhookEvent = errors.New("unknown webhook event") // ErrNotAuthenticated is returned when trying to use an authenticated method without setting a token ErrNotAuthenticated = errors.New("client not authenticated, call Register() or SetToken() first") )
Common API errors These predefined errors can be used for comparison with errors.Is().
Functions ¶
func ComputeSignature ¶
ComputeSignature computes the HMAC-SHA256 signature for a webhook payload. This is primarily useful for testing webhook implementations.
The returned signature is in the format "sha256=<hex_signature>", which matches the format used in the X-Webhook-Signature header.
Example:
payload := []byte(`{"event":"message.incoming"}`)
signature := waga.ComputeSignature(payload, "your-secret")
// Use signature to set X-Webhook-Signature header in test requests
func FormatGroupID ¶
FormatGroupID formats a group ID to WhatsApp group JID format. If the groupID already contains "@", it is returned as-is. Otherwise, "@g.us" is appended to create a valid group JID.
Example:
groupID := waga.FormatGroupID("1234567890") // "1234567890@g.us"
func FormatMSISDN ¶
FormatMSISDN formats a phone number to WhatsApp JID format for individual contacts. If the phoneNumber already contains "@", it is returned as-is. Otherwise, "@s.whatsapp.net" is appended to create a valid JID.
Example:
msisdn := waga.FormatMSISDN("6281234567890") // "6281234567890@s.whatsapp.net"
func IsBadRequest ¶
IsBadRequest checks if the error is a bad request error (HTTP 400). Returns true if err matches ErrBadRequest.
func IsConflict ¶
IsConflict checks if the error is a conflict error (HTTP 409). Returns true if err matches ErrConflict.
func IsForbidden ¶
IsForbidden checks if the error is a forbidden error (HTTP 403). Returns true if err matches ErrForbidden.
func IsGone ¶ added in v0.7.0
IsGone checks if the error is a gone error (HTTP 410). Returns true if err matches ErrGone.
func IsInternalServer ¶
IsInternalServer checks if the error is an internal server error (HTTP 500). Returns true if err matches ErrInternalServer.
func IsNotFound ¶
IsNotFound checks if the error is a not found error (HTTP 404). Returns true if err matches ErrNotFound.
func IsRateLimited ¶
IsRateLimited checks if the error is a rate limit error (HTTP 429). Returns true if err matches ErrRateLimited.
func IsUnauthorized ¶
IsUnauthorized checks if the error is an unauthorized error (HTTP 401). Returns true if err matches ErrUnauthorized.
func TraceIDFromContext ¶ added in v0.4.0
TraceIDFromContext returns the trace ID set by WithTraceID, or an empty string if none was set.
func WithTraceID ¶ added in v0.4.0
WithTraceID returns a context that carries a trace ID. Every SDK request made with the returned context sends the ID in the X-Trace-ID header:
ctx := waga.WithTraceID(context.Background(), "order-12345") resp, err := client.SendText(ctx, msisdn, "hello")
If no trace ID is set, the gateway generates one on receipt.
Types ¶
type AdminClient ¶ added in v0.7.0
type AdminClient struct {
// contains filtered or unexported fields
}
AdminClient is a separate, opt-in client for the gateway's operator-only admin plane. That plane is cross-tenant, bearer-gated by the gateway's ADMIN_API_SECRET, and served at the server ROOT path (not under /api/v1) — so it is kept off the tenant-facing Client to make accidental use impossible.
Construct it with NewAdminClient and the admin secret:
admin := waga.NewAdminClient(
waga.WithBaseURL("https://gateway.example.com"), // server ROOT
waga.WithAdminSecret(os.Getenv("ADMIN_API_SECRET")),
)
The admin secret is sent as "Authorization: Bearer <secret>".
func NewAdminClient ¶ added in v0.7.0
func NewAdminClient(opts ...Option) *AdminClient
NewAdminClient creates an admin-plane client. Unlike NewClient it defaults its base URL to the server ROOT (DefaultAdminBaseURL); override it with WithBaseURL to point at your gateway origin. Supply the admin secret via WithAdminSecret (or WithToken).
func (*AdminClient) Live ¶ added in v0.7.0
func (a *AdminClient) Live(ctx context.Context) (*HealthResponse, error)
Live is the liveness probe (root /health/live). It always returns 200 for a running process and requires no admin secret.
func (*AdminClient) Ready ¶ added in v0.7.0
func (a *AdminClient) Ready(ctx context.Context) (*HealthReadyResponse, error)
Ready is the readiness probe (root /health/ready). It requires no admin secret and returns the structured body for both "ready" (HTTP 200) and "not_ready" (HTTP 503) — inspect the returned Status rather than treating 503 as an error. Any other status (or a transport failure) is returned as an error.
func (*AdminClient) Session ¶ added in v0.7.0
func (a *AdminClient) Session(ctx context.Context, phone string) (*AdminSessionResponse, error)
Session returns one account's session state by bare phone number. An unknown account returns ErrNotFound (404).
func (*AdminClient) Sessions ¶ added in v0.7.0
func (a *AdminClient) Sessions(ctx context.Context) (*SessionInventory, error)
Sessions returns the reporting instance's session inventory (masked phones, honest states). An empty node returns Count 0, never an error.
type AdminSessionResponse ¶ added in v0.7.0
type AdminSessionResponse struct {
Instance string `json:"instance"`
Session SessionInventoryItem `json:"session"`
}
AdminSessionResponse is the GET /admin/sessions/{phone} response: one account's session plus the reporting instance hostname.
type AvatarResponse ¶ added in v0.7.0
type AvatarResponse struct {
JID string `json:"jid"`
URL string `json:"url"`
ID string `json:"id"`
Type string `json:"type"` // "image" (full res) or "preview" (thumbnail)
DirectPath string `json:"direct_path,omitempty"`
}
AvatarResponse is a chat's (user or group) profile picture. URL is a time-limited WhatsApp CDN link the caller downloads directly. ID doubles as the ETag: pass it back to GetAvatar as priorID to get ErrNotModified (304) when the picture is unchanged.
type ChatPresenceRequest ¶ added in v0.7.0
type ChatPresenceRequest struct {
// Chat is the canonical recipient (see SendMessageTextRequest.Chat).
Chat string `json:"chat"`
// State is one of composing | recording | paused.
State string `json:"state"`
}
ChatPresenceRequest sets the typing indicator in a chat.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the main SDK client for interacting with the WhatsApp Gateway API. It provides methods for authentication, messaging, webhook management, and session control.
The client is safe for concurrent use.
func NewClient ¶
NewClient creates a new SDK client with the given options.
The client can be configured with functional options:
client := waga.NewClient(
waga.WithBaseURL("https://api.example.com"),
waga.WithTimeout(60*time.Second),
waga.WithToken("existing-jwt-token"),
)
By default, the client uses:
- Base URL: http://localhost:3000/api/v1
- Timeout: 30 seconds
- User-Agent: WhatsApp-Gateway-SDK-Go/1.0
func (*Client) CheckContact ¶ added in v0.6.0
CheckContact validates whether a recipient is registered on WhatsApp.
The msisdn argument can be a plain phone number or WhatsApp JID; the gateway normalizes it and returns canonical JID details.
func (*Client) CreateGroup ¶ added in v0.7.0
func (c *Client) CreateGroup(ctx context.Context, req CreateGroupRequest) (*CreateGroupResponse, error)
CreateGroup creates a group, or a community when req.IsCommunity is set. The response carries the new group's info plus a per-participant Results slice (invited/failed members are reported there, not as an error).
Group/community management is gated server-side by GROUP_MANAGEMENT_ENABLED; when disabled the whole mutation surface is unregistered (404).
Requires authentication (call Register or SetToken first).
func (*Client) DeleteGroupPhoto ¶ added in v0.7.0
DeleteGroupPhoto removes a group's photo. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) DeleteMessage ¶
DeleteMessage deletes a previously sent message. The message will be removed from the chat for both sender and recipient.
The msisdn is the recipient's phone number, and messageID is the ID of the message to delete (returned by SendText or SendImage).
Requires authentication (call Register or SetToken first).
func (*Client) EditMessage ¶
EditMessage edits a previously sent message. It replaces the message content with newMessage.
The msisdn is the recipient's phone number, and messageID is the ID of the message to edit (returned by SendText or SendImage).
Requires authentication (call Register or SetToken first).
func (*Client) GetAvatar ¶ added in v0.7.0
func (c *Client) GetAvatar(ctx context.Context, chat string, preview bool, priorID ...string) (*AvatarResponse, error)
GetAvatar returns a chat's profile picture (user or group). preview requests the low-res thumbnail instead of the full-resolution image.
The returned AvatarResponse.ID doubles as an ETag. Pass it back on a later call as the optional priorID to enable conditional fetching: if the picture is unchanged the gateway replies 304 and this method returns ErrNotModified (check with errors.Is(err, waga.ErrNotModified)). A chat with no picture returns ErrNotFound (404); a hidden picture returns ErrForbidden (403).
Requires authentication (call Register or SetToken first).
func (*Client) GetContactInfo ¶ added in v0.7.0
GetContactInfo returns a server-side profile lookup for one user: status text, current picture id, verified business name, linked-device count, and lid.
chat is the canonical recipient (a bare number, "@s.whatsapp.net", or "@lid").
Requires authentication (call Register or SetToken first).
func (*Client) GetGroupInfo ¶ added in v0.7.0
GetGroupInfo returns a single group's full detail plus its participant roster.
chat must be a group JID ("@g.us"). The account must be a member: a non-member group returns ErrForbidden (403), an absent group returns ErrNotFound (404).
Requires authentication (call Register or SetToken first).
func (*Client) GetGroupInviteInfo ¶ added in v0.7.0
GetGroupInviteInfo previews the group behind an invite code without joining. code accepts a full chat.whatsapp.com link or a bare code. A revoked link returns an error matching ErrGone (410) — check with errors.Is(err, waga.ErrGone).
Requires authentication (call Register or SetToken first).
func (*Client) GetGroupInviteLink ¶ added in v0.7.0
func (c *Client) GetGroupInviteLink(ctx context.Context, chat string) (*GroupInviteLinkResponse, error)
GetGroupInviteLink returns a group's admin invite link. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) GetIncomingMessages ¶ added in v0.2.0
func (c *Client) GetIncomingMessages(ctx context.Context, limit int) (*IncomingMessagesResponse, error)
GetIncomingMessages fetches the most recent incoming messages buffered by the gateway for the authenticated session, newest first.
The limit parameter caps the number of messages returned. If limit <= 0, the gateway substitutes its default (10). Values above the gateway's maximum (50) are clamped server-side.
Requires authentication (call Register or SetToken first).
func (*Client) GetJobStatus ¶ added in v0.4.0
GetJobStatus fetches the status of an asynchronously queued message job.
When the gateway runs in queue mode, send endpoints return 202 Accepted with a job ID instead of a message ID. Use this method to poll the job until its Status is "completed" or "failed".
Requires authentication (call Register or SetToken first).
func (*Client) GetLoginStatus ¶
func (c *Client) GetLoginStatus(ctx context.Context) (*LoginStatus, error)
GetLoginStatus returns the current WhatsApp session status. It checks whether the WhatsApp session is authenticated and active.
Requires authentication (call Register or SetToken first).
func (*Client) GetPairCode ¶
func (c *Client) GetPairCode(ctx context.Context) (*LoginPairResponse, error)
GetPairCode generates a pair code for WhatsApp login. The pair code is an 8-character code that can be used to link the device without scanning a QR code. Users can enter the code in WhatsApp > Linked Devices.
The pair code expires after the duration specified in ExpiresIn.
Requires authentication (call Register or SetToken first).
func (*Client) GetQRCode ¶
GetQRCode generates a QR code for WhatsApp login. The format parameter specifies the response format:
- "json": returns a base64-encoded PNG image
- "html": returns an HTML img tag with the embedded QR code
The QR code can be displayed to users for scanning with the WhatsApp mobile app to link their account. The QR code expires after the duration specified in ExpiresIn.
Requires authentication (call Register or SetToken first).
func (*Client) GetToken ¶
GetToken returns the current JWT token stored in the client. Returns an empty string if no token has been set.
func (*Client) GetWebhook ¶
func (c *Client) GetWebhook(ctx context.Context) (*WebhookResponse, error)
GetWebhook returns the currently registered webhook URL. Use this to check if a webhook is configured and retrieve its URL.
Requires authentication (call Register or SetToken first).
func (*Client) Health ¶
func (c *Client) Health(ctx context.Context) (*HealthResponse, error)
Health checks the health status of the gateway service. This method does not require authentication and can be used to verify that the service is running and accessible.
func (*Client) JoinGroup ¶ added in v0.7.0
JoinGroup joins a group by invite code (a full chat.whatsapp.com link or a bare code). This mass-join vector is gated server-side by GROUP_JOIN_VIA_LINK_ENABLED (403 when disabled).
Requires authentication (call Register or SetToken first).
func (*Client) LeaveGroup ¶ added in v0.7.0
LeaveGroup leaves a group. chat must be a group JID ("@g.us"). Allowed for non-admins.
Requires authentication (call Register or SetToken first).
func (*Client) LinkSubGroup ¶ added in v0.7.0
LinkSubGroup links a sub-group under a parent community. chat is the parent community JID and childJID is the sub-group JID (both "@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) ListCommunityParticipants ¶ added in v0.7.0
func (c *Client) ListCommunityParticipants(ctx context.Context, chat string) (*CommunityParticipantsResponse, error)
ListCommunityParticipants lists every participant across a community's linked groups. chat must be the community JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) ListContacts ¶ added in v0.7.0
ListContacts returns a page of the account's locally-synced contacts. limit (gateway default 100, max 500) and offset paginate the result. An empty address book is not an error — this endpoint never 404s on empty.
Requires authentication (call Register or SetToken first).
func (*Client) ListGroups ¶ added in v0.7.0
func (c *Client) ListGroups(ctx context.Context) (*GroupListResponse, error)
ListGroups returns the account's joined groups as lightweight summaries (no participant roster; use GetGroupInfo for one group's full detail).
This is a server-hitting read subject to a per-account budget; when the budget is exhausted the gateway returns 429 (ErrRateLimited).
Requires authentication (call Register or SetToken first).
func (*Client) ListJoinRequests ¶ added in v0.7.0
func (c *Client) ListJoinRequests(ctx context.Context, chat string) (*GroupJoinRequestsResponse, error)
ListJoinRequests lists a group's pending join requests. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) ListSubGroups ¶ added in v0.7.0
ListSubGroups lists the sub-groups linked under a community. chat must be the community JID ("@g.us"). An empty list is not an error.
Requires authentication (call Register or SetToken first).
func (*Client) Logout ¶
Logout logs out from the current WhatsApp session. This disconnects the WhatsApp account and invalidates the session. After logging out, you'll need to authenticate again using GetQRCode or GetPairCode.
Requires authentication (call Register or SetToken first).
func (*Client) MarkRead ¶ added in v0.7.0
func (c *Client) MarkRead(ctx context.Context, chat string, messageIDs []string, sender string) error
MarkRead marks one or more messages in a chat as read (blue ticks).
chat is the canonical recipient. sender is the message author's JID/number and is required for group chats (pass "" for one-to-one chats).
Requires authentication (call Register or SetToken first).
func (*Client) React ¶
func (c *Client) React(ctx context.Context, msisdn, messageID, emoji string, senderMsisdn ...string) error
React adds a reaction emoji to a previously sent message. The emoji will appear on the message for all participants in the chat.
The msisdn is the recipient's phone number, messageID is the ID of the message to react to, and emoji is the emoji character(s) to use (e.g., "👍", "❤️").
Requires authentication (call Register or SetToken first).
func (*Client) Reconnect ¶
Reconnect attempts to reconnect to the existing WhatsApp session. Use this method if the connection to WhatsApp has been lost but the session is still valid. It attempts to restore the connection without requiring re-authentication.
Requires authentication (call Register or SetToken first).
func (*Client) Register ¶
func (c *Client) Register(ctx context.Context, phoneNumber, secretKey string) (*RegisterResponse, error)
Register registers a new phone number with the WhatsApp Gateway service. It retrieves and stores a JWT token for subsequent API requests.
The phoneNumber should be in international format without the "+" symbol (e.g., "6281234567890"). The secretKey is provided by the gateway service.
After successful registration, the token is automatically stored in the client and used for all authenticated requests.
func (*Client) RegisterWebhook ¶
RegisterWebhook registers a URL to receive webhook events. Webhooks allow you to receive real-time notifications for incoming and outgoing messages.
The url parameter is the endpoint where webhook events will be sent. The hmacSecret parameter is optional but highly recommended for verifying webhook signatures. If provided, all webhook payloads will include an X-Webhook-Signature header that can be verified using the WebhookVerifier.
Requires authentication (call Register or SetToken first).
func (*Client) ResetGroupInviteLink ¶ added in v0.7.0
func (c *Client) ResetGroupInviteLink(ctx context.Context, chat string) (*GroupInviteLinkResponse, error)
ResetGroupInviteLink revokes a group's current invite link and returns a freshly generated one. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) ReviewJoinRequests ¶ added in v0.7.0
func (c *Client) ReviewJoinRequests(ctx context.Context, chat, action string, participants []string) (*GroupJoinRequestsActionResponse, error)
ReviewJoinRequests approves or rejects pending join requests. action is "approve" or "reject". chat must be a group JID ("@g.us").
Partial success is a 200: inspect the returned Results for each participant.
Requires authentication (call Register or SetToken first).
func (*Client) SendAudio ¶ added in v0.6.0
func (c *Client) SendAudio(ctx context.Context, msisdn string, audio io.Reader, isPTT, isViewOnce bool, opts ...SendOption) (*SendMessageResponse, error)
SendAudio sends an audio message to the specified recipient.
The audio parameter is an io.Reader containing the audio file bytes. If isPTT is true, WhatsApp renders the audio as a voice note bubble. If isViewOnce is true, the media is sent as view-once.
func (*Client) SendChatPresence ¶ added in v0.7.0
SendChatPresence sets the typing indicator in a chat. state must be one of PresenceComposing ("typing…"), PresenceRecording ("recording audio…"), or PresencePaused (cleared).
chat is the canonical recipient.
Requires authentication (call Register or SetToken first).
func (*Client) SendDocument ¶ added in v0.6.0
func (c *Client) SendDocument(ctx context.Context, msisdn string, document io.Reader, fileName, caption string, opts ...SendOption) (*SendMessageResponse, error)
SendDocument sends a document message to the specified recipient.
fileName and caption are optional. When fileName is empty, the gateway uses its own default naming.
func (*Client) SendImage ¶
func (c *Client) SendImage(ctx context.Context, msisdn string, image io.Reader, caption string, isViewOnce bool, opts ...SendOption) (*SendMessageResponse, error)
SendImage sends an image message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. The image parameter is an io.Reader containing the image data (JPEG, PNG, etc.). The caption parameter is optional text to accompany the image. The isViewOnce parameter, if true, sends the image as a view-once media that disappears after being viewed.
Example:
file, _ := os.Open("image.jpg")
defer file.Close()
resp, err := client.SendImage(ctx, msisdn, file, "Check this out!", false)
Requires authentication (call Register or SetToken first).
func (*Client) SendLocation ¶ added in v0.3.0
func (c *Client) SendLocation(ctx context.Context, msisdn string, latitude, longitude float64, name, address string, opts ...SendOption) (*SendMessageResponse, error)
SendLocation sends a location message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. The latitude and longitude specify the geographic coordinates. The name and address parameters are optional metadata for the location pin.
Requires authentication (call Register or SetToken first).
func (*Client) SendPoll ¶ added in v0.3.0
func (c *Client) SendPoll(ctx context.Context, msisdn, question string, options []string, selectableCount int, opts ...SendOption) (*SendMessageResponse, error)
SendPoll sends a poll message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. The question is the poll question text, and options is the list of answer choices. The selectableCount limits how many options a user can select (0 means no limit).
Requires authentication (call Register or SetToken first).
func (*Client) SendSticker ¶ added in v0.3.0
func (c *Client) SendSticker(ctx context.Context, msisdn string, sticker io.Reader, opts ...SendOption) (*SendMessageResponse, error)
SendSticker sends a sticker message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. The sticker parameter is an io.Reader containing the sticker data (WebP format).
Example:
file, _ := os.Open("sticker.webp")
defer file.Close()
resp, err := client.SendSticker(ctx, msisdn, file)
Requires authentication (call Register or SetToken first).
func (*Client) SendText ¶
func (c *Client) SendText(ctx context.Context, msisdn, message string, opts ...SendOption) (*SendMessageResponse, error)
SendText sends a text message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. Use the FormatMSISDN() helper function to convert a phone number to the correct format:
msisdn := waga.FormatMSISDN("6281234567890") // "6281234567890@s.whatsapp.net"
For group messages, use the group ID in the format "groupId@g.us".
Requires authentication (call Register or SetToken first).
func (*Client) SendVideo ¶ added in v0.6.0
func (c *Client) SendVideo(ctx context.Context, msisdn string, video io.Reader, caption string, isGif, isViewOnce bool, opts ...SendOption) (*SendMessageResponse, error)
SendVideo sends a video message to the specified recipient.
The video parameter is an io.Reader containing the video file bytes. caption is optional. isGif toggles GIF-like rendering. isViewOnce controls view-once behavior.
func (*Client) SetGroupName ¶ added in v0.7.0
SetGroupName sets a group's name (subject), max 25 characters. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) SetGroupPhoto ¶ added in v0.7.0
func (c *Client) SetGroupPhoto(ctx context.Context, chat string, jpeg io.Reader) (*GroupPhotoResponse, error)
SetGroupPhoto sets a group's photo from a JPEG stream. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) SetGroupSettings ¶ added in v0.7.0
func (c *Client) SetGroupSettings(ctx context.Context, chat string, announce, locked *bool) (*GroupSettingsResponse, error)
SetGroupSettings toggles group-level settings. Pass a non-nil announce (only admins can send) and/or locked (only admins can edit group info); at least one must be supplied. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) SetGroupTopic ¶ added in v0.7.0
SetGroupTopic sets a group's topic (description), max 512 characters; an empty topic clears it. chat must be a group JID ("@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) SetToken ¶
SetToken sets the JWT token for authentication. Use this method if you already have a valid token from a previous registration. The token will be used for all subsequent API requests that require authentication.
func (*Client) UnlinkSubGroup ¶ added in v0.7.0
UnlinkSubGroup unlinks a sub-group from its parent community. chat is the parent community JID and childJID is the sub-group JID (both "@g.us").
Requires authentication (call Register or SetToken first).
func (*Client) UnregisterWebhook ¶
UnregisterWebhook removes the currently registered webhook URL. After calling this method, webhook events will no longer be sent to the previously configured endpoint.
Requires authentication (call Register or SetToken first).
func (*Client) UpdateGroupParticipants ¶ added in v0.7.0
func (c *Client) UpdateGroupParticipants(ctx context.Context, chat, action string, participants []string) (*GroupParticipantsResponse, error)
UpdateGroupParticipants mutates a group's roster. action is one of "add", "remove", "promote", or "demote". chat must be a group JID ("@g.us").
Partial success is a 200: inspect the returned Results for each participant's status ("ok", "invited" when a privacy-blocked add became an invite, or "failed" with a Code). "add" is gated server-side by GROUP_ADD_PARTICIPANTS_ENABLED (403 when disabled).
Requires authentication (call Register or SetToken first).
type CommunityParticipantItem ¶ added in v0.7.0
type CommunityParticipantItem struct {
JID string `json:"jid"`
}
CommunityParticipantItem is one member across a community's linked groups.
type CommunityParticipantsResponse ¶ added in v0.7.0
type CommunityParticipantsResponse struct {
Participants []CommunityParticipantItem `json:"participants"`
Count int `json:"count"`
}
CommunityParticipantsResponse is every participant across a community's linked groups (Count == len(Participants)).
type ContactCheckResponse ¶ added in v0.6.0
type ContactCheckResponse struct {
// Query is the original queried number.
Query string `json:"query"`
// JID is the canonical WhatsApp JID.
JID string `json:"jid"`
// IsOnWhatsApp indicates whether the number is registered on WhatsApp.
IsOnWhatsApp bool `json:"is_on_whatsapp"`
// VerifiedName is the business verified name, if available.
VerifiedName *string `json:"verified_name,omitempty"`
}
ContactCheckResponse is the result of validating a recipient number on WhatsApp.
type ContactInfoResponse ¶ added in v0.7.0
type ContactInfoResponse struct {
JID string `json:"jid"`
Status string `json:"status,omitempty"`
PictureID string `json:"picture_id,omitempty"`
VerifiedName string `json:"verified_name,omitempty"`
DeviceCount int `json:"device_count"`
LID string `json:"lid,omitempty"`
}
ContactInfoResponse is a server-side profile lookup for one user: status text, current picture id, verified business name, linked-device count, and lid.
type ContactListItem ¶ added in v0.7.0
type ContactListItem struct {
JID string `json:"jid"`
PushName string `json:"push_name,omitempty"`
FullName string `json:"full_name,omitempty"`
FirstName string `json:"first_name,omitempty"`
BusinessName string `json:"business_name,omitempty"`
}
ContactListItem is one entry in the account's locally-synced contact list.
type ContactListResponse ¶ added in v0.7.0
type ContactListResponse struct {
// Contacts is this page of synced contacts.
Contacts []ContactListItem `json:"contacts"`
// Count is the number of items in this page.
Count int `json:"count"`
// Total is the total number of synced contacts.
Total int `json:"total"`
// Note is an optional gateway-supplied advisory (e.g. sync status).
Note string `json:"note,omitempty"`
}
ContactListResponse is a page of the account's locally-synced contacts. The list reflects the synced address book, so an empty or partial result is not an error (GET /contact/ never 404s on empty).
type CreateGroupRequest ¶ added in v0.7.0
type CreateGroupRequest struct {
Name string `json:"name"`
Participants []string `json:"participants,omitempty"`
IsCommunity bool `json:"is_community,omitempty"`
LinkedParentJID string `json:"linked_parent_jid,omitempty"`
IsAnnounce bool `json:"is_announce,omitempty"`
IsLocked bool `json:"is_locked,omitempty"`
IsJoinApprovalRequired bool `json:"is_join_approval_required,omitempty"`
}
CreateGroupRequest creates a group, or a community when IsCommunity is true. An empty Participants list creates a group of just the account; adding participants at creation is gated server-side by GROUP_ADD_PARTICIPANTS_ENABLED.
type CreateGroupResponse ¶ added in v0.7.0
type CreateGroupResponse struct {
GroupJID string `json:"group_jid"`
GroupInfo *GroupInfoResponse `json:"group_info"`
Results []ParticipantResult `json:"results"`
}
CreateGroupResponse echoes the new group's JID, full info, and per-participant add results.
type ErrorResponse ¶
type ErrorResponse struct {
// Error is a human-readable error message
Error string `json:"error"`
// Code is the HTTP status code or API error code
Code int `json:"code"`
}
ErrorResponse represents an error response from the API.
type GroupInfoResponse ¶ added in v0.7.0
type GroupInfoResponse struct {
JID string `json:"jid"`
Name string `json:"name,omitempty"`
Topic string `json:"topic,omitempty"`
OwnerJID string `json:"owner_jid,omitempty"`
ParticipantCount int `json:"participant_count"`
IsAnnounce bool `json:"is_announce"`
IsLocked bool `json:"is_locked"`
IsCommunity bool `json:"is_community"`
IsEphemeral bool `json:"is_ephemeral"`
Participants []GroupParticipantItem `json:"participants"`
}
GroupInfoResponse is the full detail of a single group, including its member roster. Requires the account to be a participant (403 otherwise, 404 if absent).
type GroupInviteLinkResponse ¶ added in v0.7.0
type GroupInviteLinkResponse struct {
Chat string `json:"chat"` // resolved @g.us JID
InviteLink string `json:"invite_link"` // https://chat.whatsapp.com/<code>
}
GroupInviteLinkResponse is a group's invite link.
type GroupJoinRequestItem ¶ added in v0.7.0
type GroupJoinRequestItem struct {
JID string `json:"jid"`
RequestedAt string `json:"requested_at,omitempty"` // RFC3339
}
GroupJoinRequestItem is one pending join request.
type GroupJoinRequestsActionResponse ¶ added in v0.7.0
type GroupJoinRequestsActionResponse struct {
Chat string `json:"chat"`
Action string `json:"action"`
Results []ParticipantResult `json:"results"`
}
GroupJoinRequestsActionResponse is the per-participant outcome of an approve/reject (partial success is a 200).
type GroupJoinRequestsResponse ¶ added in v0.7.0
type GroupJoinRequestsResponse struct {
Chat string `json:"chat"`
Requests []GroupJoinRequestItem `json:"requests"`
Count int `json:"count"`
}
GroupJoinRequestsResponse lists a group's pending join requests.
type GroupListItem ¶ added in v0.7.0
type GroupListItem struct {
JID string `json:"jid"` // the group's @g.us JID
Name string `json:"name,omitempty"`
Topic string `json:"topic,omitempty"`
OwnerJID string `json:"owner_jid,omitempty"`
ParticipantCount int `json:"participant_count"`
IsAnnounce bool `json:"is_announce"` // only admins can send
IsLocked bool `json:"is_locked"` // only admins can edit group info
IsCommunity bool `json:"is_community"` // this group is a community parent
}
GroupListItem is one entry in the account's joined-groups list (a lightweight summary with no participant roster).
type GroupListResponse ¶ added in v0.7.0
type GroupListResponse struct {
Groups []GroupListItem `json:"groups"`
Count int `json:"count"`
}
GroupListResponse is the account's joined groups. Not paginated; Count always equals len(Groups).
type GroupParticipantItem ¶ added in v0.7.0
type GroupParticipantItem struct {
JID string `json:"jid"`
PhoneNumber string `json:"phone_number,omitempty"`
LID string `json:"lid,omitempty"`
IsAdmin bool `json:"is_admin"`
IsSuperAdmin bool `json:"is_super_admin"`
}
GroupParticipantItem is one member in a group's roster.
type GroupParticipantsResponse ¶ added in v0.7.0
type GroupParticipantsResponse struct {
GroupJID string `json:"group_jid"`
Action string `json:"action"`
Results []ParticipantResult `json:"results"`
}
GroupParticipantsResponse is the per-participant outcome of a roster mutation (partial success is a 200, never an overall error).
type GroupPhotoResponse ¶ added in v0.7.0
type GroupPhotoResponse struct {
PictureID string `json:"picture_id,omitempty"`
Removed bool `json:"removed,omitempty"`
}
GroupPhotoResponse reports the new picture id (on set) or removal.
type GroupSettingsResponse ¶ added in v0.7.0
type GroupSettingsResponse struct {
GroupJID string `json:"group_jid"`
Applied []string `json:"applied"`
}
GroupSettingsResponse reports which settings were applied (e.g. ["announce"]).
type HealthComponent ¶ added in v0.7.0
type HealthComponent struct {
Connected bool `json:"connected"`
Enabled bool `json:"enabled,omitempty"` // queue only
}
HealthComponent is one dependency's health in a readiness probe.
type HealthReadyResponse ¶ added in v0.7.0
type HealthReadyResponse struct {
Status string `json:"status"` // "ready" | "not_ready"
Timestamp string `json:"timestamp"`
Database *HealthComponent `json:"database,omitempty"`
Queue *HealthComponent `json:"queue,omitempty"`
}
HealthReadyResponse is the GET /health/ready body (returned for both 200 "ready" and 503 "not_ready"). Inspect Status to branch.
type HealthResponse ¶
type HealthResponse struct {
// Status is the health status of the service (e.g., "ok", "degraded")
Status string `json:"status"`
// Timestamp is the ISO 8601 timestamp of the health check
Timestamp string `json:"timestamp"`
}
HealthResponse represents the response from Health.
type IncomingEventMessage ¶
type IncomingEventMessage string
IncomingEventMessage represents the type of incoming message event.
const ( // IncomingEventMessageMessageIncoming is emitted when a new message is received IncomingEventMessageMessageIncoming IncomingEventMessage = "message.incoming" )
type IncomingMessage ¶ added in v0.2.0
type IncomingMessage struct {
// MessageId is the unique identifier for the message
MessageId string `json:"message_id"`
// Chat is the chat ID where the message was received
Chat string `json:"chat"`
// From is the sender's phone number in WhatsApp JID format
From string `json:"from"`
// IsGroup indicates whether the message was received in a group chat
IsGroup bool `json:"is_group"`
// AddressingMode is the JID addressing mode of the chat ("pn" or "lid").
AddressingMode string `json:"addressing_mode,omitempty"`
// PushName is the display name of the sender
PushName string `json:"push_name"`
// Timestamp is the Unix timestamp when the message was received
Timestamp int64 `json:"timestamp"`
// Text is the text content of the message (for text messages)
Text string `json:"text,omitempty"`
// Type is the message type (text, image, video, audio, or document)
Type IncomingMessageType `json:"type"`
// Media contains media metadata for non-text messages.
// Note: Url is not populated by /message/incoming in v1; only Type, MimeType,
// Size, Filename, and Caption are filled. Use webhooks for media URLs.
Media *IncomingMessageMediaInfo `json:"media,omitempty"`
}
IncomingMessage represents a single received message returned by the GET /message/incoming endpoint. Field names mirror IncomingWebhookPayload (minus the Event envelope) so consumers see a consistent vocabulary across the webhook delivery and the polled inbox.
type IncomingMessageMediaInfo ¶
type IncomingMessageMediaInfo struct {
// Type is the media type (image, video, audio, or document)
Type IncomingMessageType `json:"type"`
// Url is the direct URL to download the media file. In webhooks it mirrors
// StorageURL when the gateway stored the media, otherwise WhatsappURL.
Url string `json:"url"`
// StorageURL is the gateway-hosted URL when the media was downloaded and
// stored (webhooks only)
StorageURL string `json:"storage_url,omitempty"`
// WhatsappURL is the raw WhatsApp media URL used when storage was skipped
// or failed (webhooks only)
WhatsappURL string `json:"whatsapp_url,omitempty"`
// MimeType is the MIME type of the media file
MimeType string `json:"mime_type"`
// Filename is the original filename of the media file (if applicable)
Filename string `json:"filename,omitempty"`
// Caption is the text caption accompanying the media (if applicable)
Caption string `json:"caption,omitempty"`
// Size is the file size in bytes (if available)
Size int `json:"size,omitempty"`
// Sha256 is the hex-encoded SHA-256 hash of the media file (webhooks only)
Sha256 string `json:"sha256,omitempty"`
}
IncomingMessageMediaInfo contains media information for incoming messages with attachments. This includes images, videos, audio, and documents.
type IncomingMessageType ¶
type IncomingMessageType string
IncomingMessageType represents the type of incoming message content.
const ( // IncomingMessageTypeText represents a text message IncomingMessageTypeText IncomingMessageType = "text" // IncomingMessageTypeImage represents an image message IncomingMessageTypeImage IncomingMessageType = "image" // IncomingMessageTypeVideo represents a video message IncomingMessageTypeVideo IncomingMessageType = "video" // IncomingMessageTypeAudio represents an audio message IncomingMessageTypeAudio IncomingMessageType = "audio" // IncomingMessageTypeDocument represents a document message IncomingMessageTypeDocument IncomingMessageType = "document" // IncomingMessageTypeSticker represents a sticker message IncomingMessageTypeSticker IncomingMessageType = "sticker" // IncomingMessageTypeLocation represents a location message. // Webhook payloads carry Latitude/Longitude/Name/Address; the polled // /message/incoming endpoint reports only the type. IncomingMessageTypeLocation IncomingMessageType = "location" // IncomingMessageTypePoll represents a poll message. // Webhook payloads carry Question/Options/SelectableCount. IncomingMessageTypePoll IncomingMessageType = "poll" // IncomingMessageTypeContact represents a contact message (reported only // by the polled /message/incoming endpoint; no detail fields) IncomingMessageTypeContact IncomingMessageType = "contact" // IncomingMessageTypeUnknown is reported for message types the gateway // does not specifically model IncomingMessageTypeUnknown IncomingMessageType = "unknown" )
type IncomingMessagesResponse ¶ added in v0.2.0
type IncomingMessagesResponse struct {
// Success indicates the request completed successfully
Success bool `json:"success"`
// Timestamp is the Unix milliseconds when the response was generated
Timestamp int64 `json:"timestamp"`
// Count is the number of messages returned (<= requested limit)
Count int `json:"count"`
// Messages is the list of incoming messages, newest first
Messages []IncomingMessage `json:"messages"`
}
IncomingMessagesResponse represents the response from the GET /message/incoming endpoint. Messages are sorted newest first.
type IncomingWebhookPayload ¶
type IncomingWebhookPayload struct {
// Event is the type of event (always "message.incoming")
Event IncomingEventMessage `json:"event"`
// Chat is the chat ID where the message was received
Chat string `json:"chat"`
// From is the sender's phone number in WhatsApp JID format
From string `json:"from"`
// IsGroup indicates whether the message was received in a group chat
IsGroup bool `json:"is_group"`
// AddressingMode is the JID addressing mode of the chat ("pn" or "lid").
AddressingMode string `json:"addressing_mode,omitempty"`
// MessageId is the unique identifier for the message
MessageId string `json:"message_id"`
// PushName is the display name of the sender
PushName string `json:"push_name"`
// Timestamp is the Unix timestamp when the message was received
Timestamp int64 `json:"timestamp"`
// Text is the text content of the message (for text messages)
Text string `json:"text,omitempty"`
// Type is the message type (see IncomingMessageType constants)
Type IncomingMessageType `json:"type"`
// Media contains media information for image/video/audio/document/sticker
Media *IncomingMessageMediaInfo `json:"media,omitempty"`
// Location fields (Type == IncomingMessageTypeLocation).
// Latitude/Longitude are pointers because (0,0) is a valid location.
Latitude *float64 `json:"latitude,omitempty"`
Longitude *float64 `json:"longitude,omitempty"`
Name string `json:"name,omitempty"`
Address string `json:"address,omitempty"`
// Poll fields (Type == IncomingMessageTypePoll).
Question string `json:"question,omitempty"`
Options []string `json:"options,omitempty"`
SelectableCount int `json:"selectable_count,omitempty"`
}
IncomingWebhookPayload represents the payload sent to webhooks for incoming message events. This contains all information about received messages.
type JobStatusResponse ¶ added in v0.4.0
type JobStatusResponse struct {
// JobID is the identifier returned when the message was queued
JobID string `json:"job_id"`
// Status is one of "queued", "processing", "completed", or "failed"
Status string `json:"status"`
// MessageID is the WhatsApp message ID once the job completed
MessageID *string `json:"message_id,omitempty"`
// Error describes why the job failed, if it did
Error *string `json:"error,omitempty"`
// CreatedAt is when the job was created
CreatedAt string `json:"created_at"`
// CompletedAt is when the job finished, if it has
CompletedAt *string `json:"completed_at,omitempty"`
}
JobStatusResponse represents the response from the GET /message/job/:job_id endpoint, used to poll the status of an asynchronously queued message job.
type JoinGroupResponse ¶ added in v0.7.0
type JoinGroupResponse struct {
GroupJID string `json:"group_jid"`
}
JoinGroupResponse is the JID whatsmeow returned for a join-by-link (the group, or a pending membership-approval request — whatsmeow does not distinguish).
type LoginPairResponse ¶
type LoginPairResponse struct {
// PairCode is the 8-character code for linking the device
PairCode string `json:"pair_code"`
// ExpiresIn is the number of seconds until the pair code expires
ExpiresIn int `json:"expires_in"`
}
LoginPairResponse represents the response when requesting a pair code for login. The pair code can be used to link the WhatsApp account without scanning a QR code.
type LoginQrResponse ¶
type LoginQrResponse struct {
// QrCode is the base64-encoded QR code image or HTML img tag
QrCode string `json:"qr_code"`
// ExpiresIn is the number of seconds until the QR code expires
ExpiresIn int `json:"expires_in"`
}
LoginQrResponse represents the response when requesting a QR code for login. The QR code can be displayed to users for scanning with the WhatsApp mobile app.
type LoginStatus ¶
type LoginStatus struct {
// Authenticated is true if the session is active and authenticated
Authenticated bool `json:"authenticated"`
}
LoginStatus represents the response from GetLoginStatus. It indicates whether the WhatsApp session is currently authenticated.
type MarkReadRequest ¶ added in v0.7.0
type MarkReadRequest struct {
// Chat is the canonical recipient (see SendMessageTextRequest.Chat).
Chat string `json:"chat"`
// MessageIDs are the message IDs to mark read.
MessageIDs []string `json:"message_ids"`
// Sender is the message author's JID/number; required for group chats.
Sender string `json:"sender,omitempty"`
}
MarkReadRequest marks one or more messages in a chat as read (blue ticks).
type MessageDeleteRequest ¶
type MessageDeleteRequest struct {
// MessageId is the ID of the message to delete
MessageId string `json:"message_id"`
// Msisdn is the recipient's phone number in WhatsApp JID format
Msisdn string `json:"msisdn"`
}
MessageDeleteRequest represents a request to delete a previously sent message.
type MessageEditRequest ¶
type MessageEditRequest struct {
// MessageId is the ID of the message to edit
MessageId string `json:"message_id"`
// Msisdn is the recipient's phone number in WhatsApp JID format
Msisdn string `json:"msisdn"`
// NewMessage is the updated message content
NewMessage string `json:"new_message"`
}
MessageEditRequest represents a request to edit a previously sent message.
type MessageReactRequest ¶
type MessageReactRequest struct {
// MessageId is the ID of the message to react to
MessageId string `json:"message_id"`
// Msisdn is the recipient's phone number in WhatsApp JID format
Msisdn string `json:"msisdn"`
// Emoji is the emoji reaction to add
Emoji string `json:"emoji"`
// SenderMsisdn is optional and should be set when reacting to an incoming
// message from another sender (e.g. group chats).
SenderMsisdn string `json:"sender_msisdn,omitempty"`
}
MessageReactRequest represents a request to add a reaction to a message.
type Option ¶
type Option func(*Client)
Option configures the SDK client. Options are applied when creating a new client with NewClient.
func WithAdminSecret ¶ added in v0.7.0
WithAdminSecret sets the operator admin secret sent as the Bearer credential on admin-plane requests. It is an alias for WithToken, named for admin usage.
func WithBaseURL ¶
WithBaseURL sets the base URL for the API. Use this option to connect to a different WhatsApp Gateway server.
The default base URL is "http://localhost:3000/api/v1".
Example:
client := waga.NewClient(waga.WithBaseURL("https://api.example.com"))
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client for making API requests. Use this option to customize HTTP behavior such as timeouts, redirects, transport settings, or proxy configuration.
Example:
httpClient := &http.Client{
Timeout: 60 * time.Second,
Transport: &http.Transport{...},
}
client := waga.NewClient(waga.WithHTTPClient(httpClient))
func WithTimeout ¶
WithTimeout sets the HTTP client timeout for API requests. The timeout applies to the entire HTTP request, including connection time, redirects, and reading the response body.
The default timeout is 30 seconds.
Example:
client := waga.NewClient(waga.WithTimeout(60 * time.Second))
func WithToken ¶
WithToken sets a pre-existing JWT token for authentication. Use this option if you already have a valid token from a previous registration and want to skip the registration step.
The token will be used for all authenticated API requests.
Example:
client := waga.NewClient(waga.WithToken("your-jwt-token"))
func WithUserAgent ¶
WithUserAgent sets a custom User-Agent header for API requests. Use this option to identify your application in API requests.
The default User-Agent is "WhatsApp-Gateway-SDK-Go/1.0".
Example:
client := waga.NewClient(waga.WithUserAgent("MyApp/1.0"))
type OutgoingEventMessage ¶
type OutgoingEventMessage string
OutgoingEventMessage represents the type of outgoing message event. These events are sent to webhooks to track message delivery status.
const ( // OutgoingEventMessageMessageQueued is emitted when a message is added to the queue OutgoingEventMessageMessageQueued OutgoingEventMessage = "message.queued" // OutgoingEventMessageMessageSent is emitted when a message is successfully sent OutgoingEventMessageMessageSent OutgoingEventMessage = "message.sent" // OutgoingEventMessageMessageFailed is emitted when a message fails to send OutgoingEventMessageMessageFailed OutgoingEventMessage = "message.failed" )
type OutgoingWebhookPayload ¶
type OutgoingWebhookPayload struct {
// Event is the type of event that occurred
Event OutgoingEventMessage `json:"event"`
// JobId is the unique identifier for the message job
JobId string `json:"job_id"`
// To is the recipient's phone number in WhatsApp JID format
To string `json:"to"`
// PhoneNumber is the sender's phone number
PhoneNumber string `json:"phone_number"`
// Timestamp is the Unix timestamp of the event
Timestamp int64 `json:"timestamp"`
// MessageId is the unique identifier for the message
MessageId string `json:"message_id"`
// Error is the failure reason carried by message.failed (and populated on
// message.sent/queued when a reason exists); empty on success.
Error string `json:"error,omitempty"`
// Metadata contains additional optional information about the message
Metadata *map[string]interface{} `json:"metadata,omitempty"`
}
OutgoingWebhookPayload represents the payload sent to webhooks for outgoing message events. These events track the delivery status of messages sent through the API.
type ParticipantInvite ¶ added in v0.7.0
type ParticipantInvite struct {
Code string `json:"code"`
ExpiresAt time.Time `json:"expires_at,omitempty"`
}
ParticipantInvite is present on a ParticipantResult when an add was converted to an invite because the target's privacy blocks a direct add.
type ParticipantResult ¶ added in v0.7.0
type ParticipantResult struct {
JID string `json:"jid"`
LID string `json:"lid,omitempty"`
Status string `json:"status"`
Code int `json:"code,omitempty"`
Invite *ParticipantInvite `json:"invite,omitempty"`
}
ParticipantResult is the per-participant outcome shared by every batch mutation. Status is one of "ok", "invited" (add converted to an invite), or "failed"; Code carries the underlying error code when failed.
type PresenceState ¶ added in v0.7.0
type PresenceState = string
PresenceState is a chat typing-indicator state.
const ( // PresenceComposing shows the "typing…" indicator. PresenceComposing PresenceState = "composing" // PresenceRecording shows the "recording audio…" indicator. PresenceRecording PresenceState = "recording" // PresencePaused clears the typing indicator. PresencePaused PresenceState = "paused" )
type RegisterRequest ¶
type RegisterRequest struct {
PhoneNumber string `json:"phone_number"`
SecretKey string `json:"secret_key"`
}
RegisterRequest represents a registration request for a new phone number. It contains the phone number and secret key required to authenticate with the WhatsApp Gateway service and obtain a JWT token.
type RegisterResponse ¶
type RegisterResponse struct {
// Token is the JWT authentication token for API requests
Token string `json:"token"`
}
RegisterResponse represents the response from a successful registration. It contains the JWT token that should be used for subsequent API requests.
type SDKError ¶
type SDKError struct {
// Code is the HTTP status code or API error code
Code int `json:"code"`
// Message is the error message describing what went wrong
Message string `json:"error"`
// TraceID is the gateway's X-Trace-ID for this request, if the response
// carried one. Use it to correlate the failure with gateway logs.
TraceID string `json:"-"`
}
SDKError represents an error returned by the WhatsApp Gateway API. It contains both an HTTP status code and a human-readable error message.
func NewSDKError ¶
NewSDKError creates a new SDKError with the given code and message. Use this function to create custom SDK errors with specific codes and messages.
Example:
err := waga.NewSDKError(418, "I'm a teapot")
type SendLocationMessageRequest ¶ added in v0.3.0
type SendLocationMessageRequest struct {
// Chat is the canonical recipient (see SendMessageTextRequest.Chat).
Chat string `json:"chat,omitempty"`
// Msisdn is the recipient in WhatsApp JID format.
//
// Deprecated: use Chat. Msisdn remains a permanent back-compat alias.
Msisdn string `json:"msisdn,omitempty"`
// Latitude is the geographic latitude of the location
Latitude float64 `json:"latitude"`
// Longitude is the geographic longitude of the location
Longitude float64 `json:"longitude"`
// Name is the optional name of the location
Name string `json:"name,omitempty"`
// Address is the optional address of the location
Address string `json:"address,omitempty"`
// ReplyToID quotes an existing message by ID (optional).
ReplyToID string `json:"reply_to_id,omitempty"`
// ReplyToSender is the number/JID of the quoted message's author (optional).
ReplyToSender string `json:"reply_to_sender,omitempty"`
// ReplyToText is an optional caller-supplied preview of the quoted message.
ReplyToText string `json:"reply_to_text,omitempty"`
// Mentions are the numbers/JIDs to @-tag (optional).
Mentions []string `json:"mentions,omitempty"`
}
SendLocationMessageRequest represents a request to send a location message.
type SendMessageResponse ¶
type SendMessageResponse struct {
// Success indicates whether the message was successfully sent or queued
Success bool `json:"success"`
// MessageId is the unique identifier for the sent message (direct mode)
MessageId string `json:"message_id,omitempty"`
// Status is the job status in queue mode (e.g. "queued")
Status string `json:"status,omitempty"`
// JobID identifies the queued job in queue mode; poll it with GetJobStatus
JobID string `json:"job_id,omitempty"`
// Chat is the resolved canonical recipient JID the gateway addressed.
Chat string `json:"chat"`
}
SendMessageResponse represents the response from sending a message.
The populated fields depend on the gateway's delivery mode:
- Direct mode (HTTP 200): MessageId holds the sent WhatsApp message ID.
- Queue mode (HTTP 202): Status is "queued" and JobID holds the job identifier — poll it with GetJobStatus to obtain the message ID once the job completes. MessageId is empty in this case.
type SendMessageTextRequest ¶
type SendMessageTextRequest struct {
// Chat is the canonical recipient: a bare number, a user JID
// ("@s.whatsapp.net"), a group JID ("@g.us"), or a "@lid". When both Chat
// and Msisdn are set, the gateway resolves Chat.
Chat string `json:"chat,omitempty"`
// Msisdn is the recipient in WhatsApp JID format.
//
// Deprecated: use Chat. Msisdn remains a permanent back-compat alias.
Msisdn string `json:"msisdn,omitempty"`
// Message is the text content to send
Message string `json:"message"`
// ReplyToID quotes an existing message by ID (optional).
ReplyToID string `json:"reply_to_id,omitempty"`
// ReplyToSender is the number/JID of the quoted message's author (optional).
ReplyToSender string `json:"reply_to_sender,omitempty"`
// ReplyToText is an optional caller-supplied preview of the quoted message.
ReplyToText string `json:"reply_to_text,omitempty"`
// Mentions are the numbers/JIDs to @-tag (optional).
Mentions []string `json:"mentions,omitempty"`
}
SendMessageTextRequest represents a request to send a text message.
type SendOption ¶ added in v0.7.0
type SendOption func(*sendConfig)
SendOption configures a single send call — canonical chat addressing, a reply-to quote, @-mentions, and (see WithIdempotencyKey) send idempotency. Options are applied left-to-right and are accepted by every SendXxx method as a trailing variadic, so existing call sites keep compiling unchanged.
func WithChat ¶ added in v0.7.0
func WithChat(chat string) SendOption
WithChat sets the canonical recipient (a bare number, a user JID, a group JID "@g.us", or a "@lid"). It takes precedence over the positional recipient passed to the send method (which the gateway treats as the deprecated msisdn alias).
func WithIdempotencyKey ¶ added in v0.7.0
func WithIdempotencyKey(key string) SendOption
WithIdempotencyKey attaches an Idempotency-Key header to the send. Reusing the same key replays the gateway's original response (200 with Idempotent-Replay: true); an in-flight duplicate returns 409 (ErrConflict) and the same key with a different request body returns 422.
For the multipart media sends (image/audio/video/document/sticker) the retry must supply identical file content (and the same fields): the gateway keys idempotency on a hash of the raw request body, so a retry that streams different bytes is a different body (422), not a replay.
func WithMentions ¶ added in v0.7.0
func WithMentions(mentions ...string) SendOption
WithMentions @-tags the given numbers/JIDs in the outgoing message.
func WithReply ¶ added in v0.7.0
func WithReply(messageID, sender, quotedText string) SendOption
WithReply quotes an existing message. messageID and sender identify the quoted message and its author; quotedText is an optional caller-supplied preview of the quoted content (the gateway is storeless and does not look it up).
type SendPollMessageRequest ¶ added in v0.3.0
type SendPollMessageRequest struct {
// Chat is the canonical recipient (see SendMessageTextRequest.Chat).
Chat string `json:"chat,omitempty"`
// Msisdn is the recipient in WhatsApp JID format.
//
// Deprecated: use Chat. Msisdn remains a permanent back-compat alias.
Msisdn string `json:"msisdn,omitempty"`
// Question is the poll question text
Question string `json:"question"`
// Options is the list of poll options
Options []string `json:"options"`
// SelectableCount is the optional maximum number of options a user can select
SelectableCount int `json:"selectable_count,omitempty"`
// ReplyToID quotes an existing message by ID (optional).
ReplyToID string `json:"reply_to_id,omitempty"`
// ReplyToSender is the number/JID of the quoted message's author (optional).
ReplyToSender string `json:"reply_to_sender,omitempty"`
// ReplyToText is an optional caller-supplied preview of the quoted message.
ReplyToText string `json:"reply_to_text,omitempty"`
// Mentions are the numbers/JIDs to @-tag (optional).
Mentions []string `json:"mentions,omitempty"`
}
SendPollMessageRequest represents a request to send a poll message.
type SessionEvent ¶ added in v0.7.0
type SessionEvent struct {
// Event is the session.* event type.
Event WebhookEventType `json:"event"`
// PhoneNumber is the account the event concerns.
PhoneNumber string `json:"phone_number"`
// JID is the account's device JID.
JID string `json:"jid"`
// Timestamp is the Unix timestamp of the event.
Timestamp int64 `json:"timestamp"`
// OnConnect (session.logged_out) is true when the logout happened while
// (re)connecting rather than via an explicit remote logout.
OnConnect bool `json:"on_connect,omitempty"`
// Reason (session.logged_out, session.connect_failure) is the numeric reason code.
Reason int `json:"reason,omitempty"`
// ReasonText (session.logged_out, session.banned, session.connect_failure)
// is the human-readable reason.
ReasonText string `json:"reason_text,omitempty"`
// Code (session.banned) is the numeric ban code.
Code int `json:"code,omitempty"`
// ExpiresIn (session.banned) is the ban duration in seconds.
ExpiresIn int `json:"expires_in,omitempty"`
// Message (session.connect_failure) is the failure message.
Message string `json:"message,omitempty"`
}
SessionEvent is the flat envelope the gateway emits for session.* lifecycle events. The envelope fields (Event, PhoneNumber, JID, Timestamp) are always present; the remaining fields are event-specific extras and are zero when the event does not carry them:
- session.logged_out: OnConnect, Reason, ReasonText
- session.banned: Code, ReasonText, ExpiresIn
- session.connect_failure: Reason, ReasonText, Message
- session.connected / disconnected / replaced: envelope only
type SessionInventory ¶ added in v0.7.0
type SessionInventory struct {
Instance string `json:"instance"`
Count int `json:"count"`
Sessions []SessionInventoryItem `json:"sessions"`
}
SessionInventory is the GET /admin/sessions response. Instance identifies the reporting node (hostname); the view is per-instance by design.
type SessionInventoryItem ¶ added in v0.7.0
type SessionInventoryItem struct {
PhoneMasked string `json:"phone_masked"`
State string `json:"state"` // connected|disconnected|never_paired|logged_out|banned
Source string `json:"source"` // in-memory | store
Reason string `json:"reason,omitempty"`
LastSeen time.Time `json:"last_seen"`
BanExpiresAt *time.Time `json:"ban_expires_at,omitempty"`
}
SessionInventoryItem is the per-instance view of one account: masked phone, honest lifecycle state, and where the state was observed.
type SubGroupItem ¶ added in v0.7.0
type SubGroupItem struct {
JID string `json:"jid"`
Name string `json:"name,omitempty"`
IsDefaultSubGroup bool `json:"is_default_sub_group"`
}
SubGroupItem is one linked group under a community. The default sub-group is the community's announcement group.
type SubGroupListResponse ¶ added in v0.7.0
type SubGroupListResponse struct {
SubGroups []SubGroupItem `json:"sub_groups"`
Count int `json:"count"`
}
SubGroupListResponse is a community's linked sub-groups (Count == len(SubGroups)).
type SuccessResponse ¶
type SuccessResponse struct {
// Success indicates whether the operation completed successfully
Success bool `json:"success"`
}
SuccessResponse represents a generic success response from API operations.
type WebhookEvent ¶ added in v0.7.0
type WebhookEvent struct {
// Event is the parsed event type.
Event WebhookEventType
// Incoming is set for message.incoming.
Incoming *IncomingWebhookPayload
// Outgoing is set for message.queued / message.sent / message.failed.
Outgoing *OutgoingWebhookPayload
// Session is set for session.* events.
Session *SessionEvent
}
WebhookEvent is the discriminated result of ParseWebhook. Exactly one of the payload pointers is non-nil, selected by Event:
- Incoming: message.incoming
- Outgoing: message.queued / message.sent / message.failed
- Session: session.*
type WebhookEventType ¶ added in v0.7.0
type WebhookEventType string
WebhookEventType is the type discriminator carried by every webhook envelope's "event" field. It is the single catalog ParseWebhook dispatches on and mirrors the gateway's domain/queue.StatusWebhookEvent.
const ( // WebhookEventMessageIncoming is emitted for a received message. WebhookEventMessageIncoming WebhookEventType = "message.incoming" // WebhookEventMessageQueued is emitted when a message is queued. WebhookEventMessageQueued WebhookEventType = "message.queued" // WebhookEventMessageSent is emitted when a message is sent. WebhookEventMessageSent WebhookEventType = "message.sent" // WebhookEventMessageFailed is emitted when a message fails to send. WebhookEventMessageFailed WebhookEventType = "message.failed" // WebhookEventSessionLoggedOut is emitted when the account is logged out. WebhookEventSessionLoggedOut WebhookEventType = "session.logged_out" // WebhookEventSessionBanned is emitted when the account is temporarily banned. WebhookEventSessionBanned WebhookEventType = "session.banned" // WebhookEventSessionConnectFailure is emitted on a connection failure. WebhookEventSessionConnectFailure WebhookEventType = "session.connect_failure" // WebhookEventSessionConnected is emitted when the session connects. WebhookEventSessionConnected WebhookEventType = "session.connected" // WebhookEventSessionDisconnected is emitted when the session disconnects. WebhookEventSessionDisconnected WebhookEventType = "session.disconnected" // WebhookEventSessionReplaced is emitted when another process takes the socket. WebhookEventSessionReplaced WebhookEventType = "session.replaced" )
type WebhookRegisterRequest ¶
type WebhookRegisterRequest struct {
// Url is the endpoint URL where webhook events will be sent
Url string `json:"url"`
// HmacSecret is the optional secret key used to sign webhook payloads for verification
HmacSecret *string `json:"hmac_secret,omitempty"`
}
WebhookRegisterRequest represents a request to register a webhook URL. Webhooks receive real-time notifications for message events.
type WebhookResponse ¶
type WebhookResponse struct {
// URL is the currently registered webhook endpoint
URL string `json:"url"`
}
WebhookResponse represents the response from GetWebhook.
type WebhookVerifier ¶
type WebhookVerifier struct {
// contains filtered or unexported fields
}
WebhookVerifier handles verification of incoming webhook signatures. It ensures that webhook payloads are genuine and haven't been tampered with by verifying HMAC-SHA256 signatures.
Security considerations:
- Always keep your HMAC secret secure and never expose it in client-side code
- Use constant-time comparison to prevent timing attacks
- Reject webhooks with invalid or missing signatures
func NewWebhookVerifier ¶
func NewWebhookVerifier(secret string) *WebhookVerifier
NewWebhookVerifier creates a new webhook verifier with the given HMAC secret. The secret must match the one configured when registering the webhook.
Example:
verifier := waga.NewWebhookVerifier("your-hmac-secret")
func (*WebhookVerifier) ParseIncomingWebhook ¶
func (v *WebhookVerifier) ParseIncomingWebhook(payload []byte, signature string) (*IncomingWebhookPayload, error)
ParseIncomingWebhook parses and verifies an incoming message webhook payload. It returns the parsed payload if the signature is valid, or an error otherwise.
This method verifies the signature first, then unmarshals the JSON payload. If either step fails, it returns an error.
Example:
body, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-Webhook-Signature")
webhook, err := verifier.ParseIncomingWebhook(body, signature)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Message from %s: %s\n", webhook.From, webhook.Text)
func (*WebhookVerifier) ParseOutgoingWebhook ¶
func (v *WebhookVerifier) ParseOutgoingWebhook(payload []byte, signature string) (*OutgoingWebhookPayload, error)
ParseOutgoingWebhook parses and verifies an outgoing event webhook payload. It returns the parsed payload if the signature is valid, or an error otherwise.
Outgoing webhooks track the delivery status of messages sent through the API. This method verifies the signature first, then unmarshals the JSON payload.
Example:
body, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-Webhook-Signature")
webhook, err := verifier.ParseOutgoingWebhook(body, signature)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Message %s: %s\n", webhook.Event, webhook.MessageId)
func (*WebhookVerifier) ParseWebhook ¶ added in v0.7.0
func (v *WebhookVerifier) ParseWebhook(payload []byte, signature string) (*WebhookEvent, error)
ParseWebhook verifies a webhook payload's signature, then inspects its "event" field and decodes it into a discriminated WebhookEvent covering every event the gateway emits: message.incoming (Incoming), message.queued/sent/failed (Outgoing), and the session.* lifecycle events (Session). Exactly one of the WebhookEvent payload pointers is non-nil.
Use this when a single endpoint receives every webhook type. The narrower ParseIncomingWebhook / ParseOutgoingWebhook remain available.
An unrecognized event yields an error wrapping ErrUnknownWebhookEvent; an invalid signature yields ErrInvalidSignature.
Example:
ev, err := verifier.ParseWebhook(body, signature)
if err != nil {
log.Fatal(err)
}
switch ev.Event {
case waga.WebhookEventMessageIncoming:
fmt.Println("from", ev.Incoming.From)
case waga.WebhookEventSessionBanned:
fmt.Println("banned for", ev.Session.ExpiresIn, "seconds")
}
func (*WebhookVerifier) VerifySignature ¶
func (v *WebhookVerifier) VerifySignature(payload []byte, signatureHeader string) bool
VerifySignature validates the X-Webhook-Signature header from a webhook request. The signature header format is: "sha256=<hex_signature>".
This method uses constant-time comparison to prevent timing attacks. It returns false if the signature is missing, malformed, or doesn't match.
Example:
signature := r.Header.Get("X-Webhook-Signature")
if !verifier.VerifySignature(body, signature) {
return ErrInvalidSignature
}