### Install WhatsApp Go Client Source: https://github.com/piusalfred/whatsapp/blob/main/README.md Install the library using the go get command. This is the first step to using the whatsapp client in your Go project. ```bash go get github.com/piusalfred/whatsapp ``` -------------------------------- ### Navigate to Examples Directory Source: https://github.com/piusalfred/whatsapp/blob/main/docs/README.md Change the current directory to examples/bin to run the compiled example binaries. ```bash cd examples/bin ``` -------------------------------- ### Build Example Binaries Source: https://github.com/piusalfred/whatsapp/blob/main/docs/README.md Compile example binaries for the WhatsApp Cloud API. Ensure you are in the project root directory. ```bash task build-examples ``` -------------------------------- ### Basic HTTP Client Setup Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Sets up a basic HTTP client with a timeout and initializes the WhatsApp sender. ```go httpClient := &http.Client{ Timeout: 30 * time.Second, } sender := whttp.NewSender[message.Message]( whttp.WithCoreClientHTTPClient(httpClient), ) ``` -------------------------------- ### Example: Initialize and Configure Sender Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Demonstrates initializing a sender for `message.Message` type, setting a default HTTP client, and registering a request interceptor to add a unique request ID header. ```go sender := whttp.NewSender[message.Message]() sender.SetHTTPClient(http.DefaultClient) sender.SetRequestInterceptor(func(ctx context.Context, req *http.Request) error { req.Header.Add("X-Request-ID", uuid.New().String()) return nil }) ``` -------------------------------- ### Clone and Download WhatsApp Library Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/README.md Clone the repository and download the Go modules to get started with the whatsapp library. ```bash git clone https://github.com/piusalfred/whatsapp.git cd whatsapp go mod download ``` -------------------------------- ### Typical Authentication Workflow Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Demonstrates a common sequence of operations for authenticating with the API, including client initialization, app installation, and token management. ```Go // 1. Initialize client httpSender := whttp.NewSender[any]() authClient := auth.NewClient("https://graph.facebook.com", "v24.0", httpSender) // 2. Install app for system user err := authClient.InstallApp(ctx, auth.InstallAppParams{ AccessToken: adminToken, AppID: appID, SystemUserID: systemUserID, }) // 3. Set up two-step verification twoStepClient := &auth.TwoStepVerificationClient{ // ... initialization } _, err := twoStepClient.TwoStepVerification(ctx, &auth.TwoStepVerificationRequest{ SixDigitCode: "123456", PhoneNumberID: phoneNumberID, AccessToken: token, }) // 4. Refresh token when needed response, _ := refresher.RefreshAccessToken(ctx, auth.RefreshAccessTokenParams{ AccessToken: currentToken, BusinessAccountID: wabaID, }) // 5. Revoke token when done revoker.RevokeAccessToken(ctx, auth.RevokeAccessTokenParams{ AccessToken: token, BusinessAccountID: wabaID, }) ``` -------------------------------- ### Load Configuration from .env File in Go Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Example of loading environment variables from a .env file using the godotenv package and then creating a configuration reader. ```go import "github.com/joho/godotenv" func init() { godotenv.Load() } reader := config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: os.Getenv("API_VERSION"), AccessToken: os.Getenv("ACCESS_TOKEN"), PhoneNumberID: os.Getenv("PHONE_NUMBER_ID"), BusinessAccountID: os.Getenv("BUSINESS_ACCOUNT_ID"), }, nil }) ``` -------------------------------- ### Example Reader Implementation using ReaderFunc Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/config.md Demonstrates how to create a configuration reader using ReaderFunc, loading values from environment variables. Ensure necessary environment variables are set before use. ```go reader := config.ReaderFunc(func(ctx context.Context) (*Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: os.Getenv("WHATSAPP_ACCESS_TOKEN"), PhoneNumberID: os.Getenv("WHATSAPP_PHONE_NUMBER_ID"), BusinessAccountID: os.Getenv("WHATSAPP_BUSINESS_ACCOUNT_ID"), SecureRequests: false, }, nil }) ``` -------------------------------- ### InstallApp Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Installs an application for a system user. Requires admin or system user credentials. ```APIDOC ## InstallApp ### Description Installs an application for a system user. This operation requires an access token of an admin or system user. ### Method POST ### Endpoint /v1/apps ### Parameters #### Request Body - **AccessToken** (string) - Yes - Admin or system user access token - **AppID** (string) - Yes - Application ID to install - **SystemUserID** (string) - Yes - System user ID ### Request Example ```json { "AccessToken": "string", "AppID": "string", "SystemUserID": "string" } ``` ### Response #### Success Response (200) - **Success** (bool) - Whether operation succeeded #### Response Example ```json { "Success": true } ``` ``` -------------------------------- ### Install App for System User Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Installs an app for a system user using an admin token. Ensure the app meets the Ads Management API access requirements and belongs to the same Business Manager as the system user. ```go err := authClient.InstallApp(ctx, auth.InstallAppParams{ AccessToken: "admin_token", AppID: "app123", SystemUserID: "user456", }) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Constructing a Text Message with Options Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/message-client.md Use the `New` function with `WithTextMessage` option to create a text message. This example demonstrates setting the message body and preview URL. ```Go func New(recipient string, options ...Option) (*Message, error) ``` ```Go msg, err := message.New("1234567890", message.WithTextMessage(&message.Text{ Body: "Hello!", PreviewURL: true, }), ) response, err := client.SendMessage(ctx, msg) ``` -------------------------------- ### InstallApp Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Installs an app for a system user, requiring specific permissions and business manager association. ```APIDOC ## InstallApp ### Description Installs an app for a system user. ### Signature ```go func (c *Client) InstallApp(ctx context.Context, params InstallAppParams) error ``` ### Parameters #### Path Parameters - **ctx** (`context.Context`) - Required - Request context - **params.AccessToken** (string) - Required - Admin/system user token - **params.AppID** (string) - Required - App ID to install - **params.SystemUserID** (string) - Required - System user ID ### Returns - `error`: Error if installation fails ### Throws #### install app error - Condition: API request failed ### Requirements - App must have Ads Management API standard access or higher - App and system user must belong to same Business Manager ### Example ```go err := authClient.InstallApp(ctx, auth.InstallAppParams{ AccessToken: "admin_token", AppID: "app123", SystemUserID: "user456", }) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Load Configuration from Database Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Retrieves WhatsApp API configuration by querying a SQL database. This example assumes a table named `whatsapp_config` with specific columns. ```go type DatabaseConfigReader struct { db *sql.DB } func (r *DatabaseConfigReader) Read(ctx context.Context) (*config.Config, error) { row := r.db.QueryRowContext(ctx, "SELECT base_url, api_version, access_token, phone_number_id, business_account_id FROM whatsapp_config WHERE id = 1") var cfg config.Config err := row.Scan( &cfg.BaseURL, &cfg.APIVersion, &cfg.AccessToken, &cfg.PhoneNumberID, &cfg.BusinessAccountID, ) return &cfg, err } ``` -------------------------------- ### Setup WhatsApp Webhook Handlers Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/webhooks.md Demonstrates how to set up handlers for various webhook events including text messages, image messages, and status changes. Includes an error handler for webhook processing. ```Go package main import ( "context" "github.com/piusalfred/whatsapp/webhooks" ) func setupWebhooks() *webhooks.Handler { handler := webhooks.NewHandler() // Text message handler handler.OnTextMessage(webhooks.MessageHandlerFunc[webhooks.Text]( func(ctx context.Context, msgCtx *webhooks.MessageContext, text *webhooks.Text) error { log.Printf("Received from %s: %s", msgCtx.ContactName, text.Body) return nil }, )) // Image message handler handler.OnImageMessage(webhooks.MediaMessageHandlerFunc( func(ctx context.Context, msgCtx *webhooks.MessageContext, media *webhooks.MediaMessage) error { log.Printf("Received image: %s", media.Image.ID) return nil }, )) // Status update handler handler.OnMessageStatusChange(webhooks.MessageChangeValueHandlerFunc[webhooks.Status]( func(ctx context.Context, msgCtx *webhooks.MessageContext, statuses []*webhooks.Status) error { for _, status := range statuses { log.Printf("Message %s status: %s", status.ID, status.Status) } return nil }, )) // Error handler handler.OnError(func(ctx context.Context, err error) error { log.Printf("Webhook processing error: %v", err) return nil // Continue processing }) return handler } func handleWebhook(c *gin.Context) { var notification webhooks.Notification if err := c.BindJSON(¬ification); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } handler := setupWebhooks() response := handler.HandleNotification(c.Request.Context(), ¬ification) c.JSON(response.StatusCode, gin.H{}) } ``` -------------------------------- ### Create Group, Get Invite Link, and Remove Participant Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/user-phonenumber-groups.md Illustrates the process of creating a new group with participants, obtaining an invite link for the group, and removing a participant from the group. The groups client needs to be initialized with the context, reader, and sender. ```Go groupsClient := groups.NewClient(ctx, reader, sender) // Create group response, err := groupsClient.CreateGroup(ctx, &groups.CreateGroupRequest{ Subject: "Support Team", ParticipantPhoneNumbers: []string{"1234567890", "0987654321"}, }) // Get invite link link, err := groupsClient.GetGroupInviteLink(ctx, response.GroupID) fmt.Printf("Invite: %s\n", link.GroupInviteLink) // Remove participant err := groupsClient.RemoveParticipant(ctx, &groups.RemoveParticipantRequest{ GroupID: response.GroupID, PhoneNumbers: []string{"0987654321"}, }) ``` -------------------------------- ### Set Request Interceptor Example Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Example of setting a request interceptor to add a custom header to outgoing requests. This demonstrates how to use `RequestInterceptorFunc`. ```go client.SetRequestInterceptor(func(ctx context.Context, req *http.Request) error { req.Header.Add("X-Custom-Header", "value") return nil }) ``` -------------------------------- ### InstallAppParams Struct Definition Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Defines the parameters required for installing an application for a system user. Includes access token, app ID, and system user ID. ```go type InstallAppParams struct { AccessToken string // Access token of admin or system user AppID string // ID of app to install SystemUserID string // ID of system user } ``` -------------------------------- ### Configure and Send Text Message Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/README.md Example demonstrating how to configure the WhatsApp client and send a text message. Ensure you replace placeholders with your actual credentials and recipient information. ```go // Configuration reader := config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: "your_token", PhoneNumberID: "123456789", BusinessAccountID: "abcdef123", }, nil }) // Send text message client, err := message.NewClient(ctx, reader, httpSender) response, err := client.SendText(ctx, &message.Request[message.Text]{ Recipient: "1234567890", Message: &message.Text{ Body: "Hello!", PreviewURL: true, }, }) ``` -------------------------------- ### Flow JSON Structure Example Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/flows-qrcode.md An example of the JSON structure used to define a WhatsApp flow, including screens, inputs, options, and routing logic. ```json { "version": 1.0, "screens": [ { "id": "screen_1", "type": "text_input", "title": "Welcome", "body": "What is your name?", "inputs": [ { "name": "name", "type": "text", "required": true } ] }, { "id": "screen_2", "type": "list", "title": "Select Option", "options": [ { "id": "opt_1", "label": "Option 1" }, { "id": "opt_2", "label": "Option 2" } ] } ], "routing": [ { "from": "screen_1", "to": "screen_2", "condition": "always" } ] } ``` -------------------------------- ### GetPhoneNumber Example Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/user-phonenumber-groups.md Retrieve information for a specific phone number by providing its ID and desired fields. ```go response, err := phoneClient.GetPhoneNumber(ctx, &phonenumber.GetRequest{ ID: "123456789", Fields: []string{"display_phone_number", "quality_rating"}, }) ``` -------------------------------- ### User Management Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/user-phonenumber-groups.md Examples for blocking, unblocking, and listing blocked users. ```APIDOC ## Block Users ### Description Blocks a list of users. ### Method `BlockUsers` ### Parameters - `Numbers` (array of string) - Required - The phone numbers to block. - `Action` (BlockAction) - Required - The action to perform, e.g., `BlockActionBlock`. ### Request Example ```go userClient.BlockUsers(ctx, &user.BlockUserParams{ Numbers: []string{"1234567890", "0987654321"}, Action: user.BlockActionBlock, }) ``` ## Unblock Users ### Description Unblocks a list of users. ### Method `UnblockUsers` ### Parameters - `Numbers` (array of string) - Required - The phone numbers to unblock. - `Action` (BlockAction) - Required - The action to perform, e.g., `BlockActionUnblock`. ### Request Example ```go userClient.UnblockUsers(ctx, &user.BlockUserParams{ Numbers: []string{"1234567890"}, Action: user.BlockActionUnblock, }) ``` ## List Blocked Users ### Description Lists all users that have been blocked. ### Method `ListBlockedUsers` ### Parameters - `Limit` (int) - Optional - The maximum number of blocked users to return. ### Response Example ```go { "Data": [ { "BlockUsers": [ { "Input": "1234567890", "WaID": "1234567890" } ] } ] } ``` ``` -------------------------------- ### Handle Metadata in Responses Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/types.md Example of how to access metadata fields like message_id and timestamp from a response object. ```Go // In response handling var metadata pkg/types.Metadata if msgResp.MessageMetadata != nil { messageID := msgResp.MessageMetadata["message_id"].(string) timestamp := msgResp.MessageMetadata["timestamp"].(int64) } ``` -------------------------------- ### Create New Webhook Handler Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/webhooks.md Initializes a new webhook handler with default no-operation callbacks for all event types. Use this to get a basic handler instance. ```go func NewHandler() *Handler ``` ```go handler := webhooks.NewHandler() ``` -------------------------------- ### Get, List, and Update Phone Number Info Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/user-phonenumber-groups.md Shows how to retrieve information about a specific phone number, list all associated phone numbers, and update the verified name for a phone number. The phonenumber client must be initialized. ```Go phoneClient := phonenumber.NewBaseClient(reader, sender) // Get phone number info info, err := phoneClient.GetPhoneNumber(ctx, &phonenumber.GetRequest{ ID: "123456789", }) fmt.Printf("Display: %s, Quality: %s\n", info.DisplayPhoneNumber, info.QualityRating) // List all phone numbers list, err := phoneClient.ListPhoneNumbers(ctx, &phonenumber.GetRequest{}) // Update verified name _, err := phoneClient.UpdatePhoneNumberName(ctx, &phonenumber.UpdateNameRequest{ ID: "123456789", VerifiedName: "My Business", }) ``` -------------------------------- ### WhatsApp API Error Response Example Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/errors.md An example of a JSON error response from the WhatsApp API, illustrating common fields like message, type, and code. ```json { "error": { "message": "Invalid phone number", "type": "OAuthException", "code": 2005, "error_subcode": 1004, "fbtrace_id": "AY9j3..." } } ``` -------------------------------- ### Create New Base Client Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/media.md Creates a new stateless media client. Use this to initialize the media client with configuration and an HTTP sender. ```go mediaClient := media.NewBaseClient(reader, httpSender) ``` -------------------------------- ### Typical Media Upload Workflow Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/media.md Illustrates the complete process of uploading media, sending it in a message, retrieving its info, and cleaning up. ```go // 1. Create client mediaClient := media.NewBaseClient(reader, httpSender) // 2. Upload media uploadResp, err := mediaClient.Upload(ctx, &media.UploadRequest{ MediaType: media.TypeImageJPEG, Filepath: "/path/to/image.jpg", }) // 3. Use media ID in message msgResp, err := messageClient.SendImage(ctx, &message.Request[message.Image]{ Recipient: "1234567890", Message: &message.Image{ ID: uploadResp.ID, Caption: "Check this!", }, }) // 4. Later, get media info info, err := mediaClient.GetInfo(ctx, &media.BaseRequest{ MediaID: uploadResp.ID, }) // 5. Clean up when done mediaClient.Delete(ctx, &media.BaseRequest{ MediaID: uploadResp.ID, }) ``` -------------------------------- ### Create New Client with Simple Configuration Reader Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Initializes a new WhatsApp client using a simple configuration reader function. Ensure the AccessToken, APIVersion, PhoneNumberID, and BusinessAccountID are set in the environment. ```go reader := config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: os.Getenv("WHATSAPP_TOKEN"), PhoneNumberID: os.Getenv("PHONE_ID"), BusinessAccountID: os.Getenv("WABA_ID"), }, nil }) client, err := message.NewClient(ctx, reader, httpSender) ``` -------------------------------- ### Get Media Info Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/media.md Retrieves information about a specific media file using its ID. ```APIDOC ## Get Media Info ### Description Retrieves information about a specific media file using its ID. ### Method GET ### Endpoint /v1/media/{media_id}/info ### Parameters #### Path Parameters - **media_id** (string) - Yes - The ID of the media to retrieve information for. #### Query Parameters - **restrict_to_own_media** (bool) - No - Restrict results to media uploaded by this account. - **phone_number_id** (string) - No - The phone number ID (optional). ### Response #### Success Response (200) - **MessagingProduct** (string) - "whatsapp" - **URL** (string) - Media URL - **MimeType** (string) - MIME type - **SHA256** (string) - SHA256 hash of file - **FileSize** (int64) - Size in bytes - **ID** (string) - Media ID #### Response Example ```json { "MessagingProduct": "whatsapp", "URL": "https://example.com/media/media-id-12345", "MimeType": "image/jpeg", "SHA256": "a1b2c3d4e5f6...", "FileSize": 512000, "ID": "media-id-12345" } ``` ``` -------------------------------- ### Flow Management Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/INDEX.md Endpoints for creating, listing, getting, updating, publishing, and deleting flows. ```APIDOC ## POST /flows ### Description Create a new flow. ### Method POST ### Endpoint `/flows` ``` ```APIDOC ## GET /flows ### Description List all available flows. ### Method GET ### Endpoint `/flows` ``` ```APIDOC ## GET / ### Description Get details of a specific flow. ### Method GET ### Endpoint `/` ``` ```APIDOC ## PUT / ### Description Update an existing flow. ### Method PUT ### Endpoint `/` ``` ```APIDOC ## POST //publish ### Description Publish a flow. ### Method POST ### Endpoint `//publish` ``` ```APIDOC ## DELETE / ### Description Delete a flow. ### Method DELETE ### Endpoint `/` ``` ```APIDOC ## GET //assets ### Description Retrieve assets associated with a flow. ### Method GET ### Endpoint `//assets` ``` -------------------------------- ### Send a Template Message with BaseClient Source: https://github.com/piusalfred/whatsapp/blob/main/README.md Demonstrates how to initialize and use the BaseClient to send a template message. Ensure you replace placeholder values and implement a proper configuration reader. ```go package main import ( "context" "fmt" "net/http" "os" "github.com/piusalfred/whatsapp/config" "github.com/piusalfred/whatsapp/message" whttp "github.com/piusalfred/whatsapp/pkg/http" ) const recipient = "XXXXXXXXXXXXX" // Placeholder for recipient number func main() { ctx := context.Background() coreClient := whttp.NewSender[message.Message]() coreClient.SetHTTPClient(http.DefaultClient) reader := config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { // TODO: Replace with your config reader implementation conf := &config.Config{ BaseURL: "", APIVersion: "", AccessToken: "", PhoneNumberID: "", BusinessAccountID: "", AppSecret: "", AppID: "", SecureRequests: false, } return conf, nil }) baseClient, err := message.NewBaseClient(coreClient, reader) if err != nil { fmt.Printf("error creating base client: %v\n", err) os.Exit(1) } initTmpl := message.WithTemplateMessage(&message.Template{ Name: "hello_world", Language: &message.TemplateLanguage{ Code: "en_US", }, }) initTmplMessage, err := message.New(recipient, initTmpl) if err != nil { fmt.Printf("error creating initial template message: %v\n", err) os.Exit(1) } response, err := baseClient.SendMessage(ctx, initTmplMessage) if err != nil { fmt.Printf("error sending initial template message: %v\n", err) os.Exit(1) } fmt.Printf("response: %+v\n", response) } ``` -------------------------------- ### Group Management Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/INDEX.md Endpoints for creating groups, getting invite links, and managing participants. ```APIDOC ## POST //groups ### Description Create a new group. ### Method POST ### Endpoint `//groups` ``` ```APIDOC ## GET //invite ### Description Get the invite link for a group. ### Method GET ### Endpoint `//invite` ``` ```APIDOC ## POST //participants ### Description Manage participants within a group (add/remove). ### Method POST ### Endpoint `//participants` ``` -------------------------------- ### Create Base Client with Multi-Tenant Configuration Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Initializes a base WhatsApp client designed for multi-tenant environments. It extracts the tenant ID from the context and uses a map to store configurations for different tenants. ```go reader := &MultiTenantReader{ getTenantID: func(ctx context.Context) (string, error) { // Extract tenant ID from context return ctx.Value("tenant_id").(string), nil }, configStore: map[string]*config.Config{ "tenant_1": tenantConfig1, "tenant_2": tenantConfig2, }, } baseClient, err := message.NewBaseClient(httpSender, reader) ``` -------------------------------- ### Media Management Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/INDEX.md Endpoints for managing media, including getting info, deleting, uploading, and downloading. ```APIDOC ## GET / ### Description Get media information. ### Method GET ### Endpoint `/` ``` ```APIDOC ## DELETE / ### Description Delete media. ### Method DELETE ### Endpoint `/` ``` ```APIDOC ## POST /media ### Description Upload media. ### Method POST ### Endpoint `/media` ``` ```APIDOC ## GET /media?media_id= ### Description Download media. ### Method GET ### Endpoint `/media?media_id=` ``` -------------------------------- ### Create Stateful Message Client Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/message-client.md Use `NewClient` to create a stateful message client. This requires a context, configuration reader, and an HTTP message sender. Optional middlewares can be provided for request/response handling. Ensure the configuration reader is valid to avoid errors. ```go func NewClient( ctx context.Context, reader config.Reader, sender whttp.Sender[Message], middlewares ...SenderMiddleware, ) (*Client, error) ``` ```go reader := config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: "token123", PhoneNumberID: "12345", BusinessAccountID: "67890", }, nil }) coreClient := whttp.NewSender[message.Message]() coreClient.SetHTTPClient(http.DefaultClient) client, err := message.NewClient(ctx, reader, coreClient) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Phone Number Management Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/INDEX.md Endpoints for managing phone numbers, including getting info, updating, and listing. ```APIDOC ## GET / ### Description Get phone number information. ### Method GET ### Endpoint `/` ``` ```APIDOC ## PUT / ### Description Update phone number information. ### Method PUT ### Endpoint `/` ``` ```APIDOC ## GET //phone_numbers ### Description List phone numbers associated with a WhatsApp Business Account (WABA). ### Method GET ### Endpoint `//phone_numbers` ``` -------------------------------- ### Block, Unblock, and List Users Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/user-phonenumber-groups.md Demonstrates how to block users, unblock users, and list blocked users using the user client. Ensure the user client is initialized with appropriate reader and sender configurations. ```Go userClient := user.NewBaseClient(reader, sender) // Block users response, err := userClient.BlockUsers(ctx, &user.BlockUserParams{ Numbers: []string{"1234567890", "0987654321"}, Action: user.BlockActionBlock, }) // Unblock users unblockResp, err := userClient.UnblockUsers(ctx, &user.BlockUserParams{ Numbers: []string{"1234567890"}, Action: user.BlockActionUnblock, }) // List blocked users listResp, err := userClient.ListBlockedUsers(ctx, &user.ListBlockedUsersOptions{ Limit: ptr.Int(10), }) for _, userData := range listResp.Data { for _, blockedUser := range userData.BlockUsers { fmt.Printf("%s -> %s\n", blockedUser.Input, blockedUser.WaID) } } ``` -------------------------------- ### Create Client with Validated Configuration Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Initializes a new WhatsApp client after validating the configuration. This ensures that the configuration meets all necessary requirements before client instantiation. ```go conf, err := config.ReadValidate(ctx, reader) if err != nil { log.Fatalf("Invalid config: %v", err) } client, err := message.NewClient(ctx, reader, httpSender) ``` -------------------------------- ### Handle Get Phone Number API Errors Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/errors.md This snippet shows how to check for errors during an API call to retrieve phone number information. ```go phoneResp, err := phoneClient.GetPhoneNumber(ctx, &phonenumber.GetRequest{...}) if err != nil { // API communication error } ``` -------------------------------- ### PreviewURLConfigOptions Struct Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/flows-qrcode.md Defines configuration options for generating preview URLs for WhatsApp Flows. ```go type PreviewURLConfigOptions struct { Format string // URL format ExpirationSeconds int // Expiration in seconds AssetRepresentations []string // Asset representations } ``` -------------------------------- ### Create New Authentication Client Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Instantiates a new authentication client. Requires the base URL, API version, and an HTTP sender. ```go httpSender := whttp.NewSender[any]() httpSender.SetHTTPClient(http.DefaultClient) authClient := auth.NewClient( "https://graph.facebook.com", "v24.0", httpSender, ) ``` -------------------------------- ### Get Group Invite Link Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/user-phonenumber-groups.md Retrieves the shareable invite link for a specified group ID. This link can be used to invite new members to the group. ```go link, err := groupsClient.GetGroupInviteLink(ctx, "group123") fmt.Println(link.GroupInviteLink) ``` -------------------------------- ### Create Stateless Message Client Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/message-client.md Use `NewBaseClient` to create a stateless message client. This function requires an HTTP message sender and a configuration reader. It returns an initialized stateless client or an error if the configuration cannot be read. ```go func NewBaseClient( sender whttp.Sender[Message], reader config.Reader, ) (*BaseClient, error) ``` ```go coreClient := whttp.NewSender[message.Message]() baseClient, err := message.NewBaseClient(coreClient, reader) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Copy Environment Template Source: https://github.com/piusalfred/whatsapp/blob/main/docs/README.md Copy the environment template to be configured with your API credentials. This file is located in the examples/bin directory. ```bash cp examples/api.env examples/bin/api.env ``` -------------------------------- ### Get Media Information Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/media.md Retrieves information about an uploaded media file using its Media ID. Returns MIME type and file size upon success. ```go info, err := mediaClient.GetInfo(ctx, &media.BaseRequest{ MediaID: "media123", }) if err != nil { log.Fatal(err) } fmt.Printf("MIME: %s, Size: %d bytes\n", info.MimeType, info.FileSize) ``` -------------------------------- ### Validate Configuration Early in Go Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Shows how to read and validate configuration early in your application to catch errors before they cause issues. ```go conf, err := config.ReadValidate(ctx, reader) if err != nil { log.Fatalf("Invalid config: %v", err) } ``` -------------------------------- ### Prepend Middlewares Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Adds one or more middleware components to the beginning of the existing middleware chain. These will execute first. ```go func (core *CoreClient[T]) PrependMiddlewares(mws ...Middleware[T]) ``` -------------------------------- ### Create Client with Cached Configuration Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Initializes a WhatsApp client using a cached configuration reader. This improves performance by reducing redundant configuration reads. The cache has a specified Time-To-Live (TTL). ```go cachedReader := &CachedConfigReader{ reader: fileReader, ttl: 5 * time.Minute, } client, err := message.NewClient(ctx, cachedReader, httpSender) // Later, reload if needed client.ReloadConfig(ctx) ``` -------------------------------- ### WhatsApp Configuration Usage Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/config.md Demonstrates how to create and read WhatsApp API configuration using a custom reader function. It's recommended to use `ReadValidate()` for a combined read and validation step. ```go package main import ( "context" "github.com/piusalfred/whatsapp/config" ) func main() { // Create a reader reader := config.ReaderFunc(func(ctx context.Context) (*Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: "your-token", PhoneNumberID: "your-phone-id", BusinessAccountID: "your-business-id", SecureRequests: false, }, nil }) ctx := context.Background() // Read and validate in one call conf, err := config.ReadValidate(ctx, reader) if err != nil { panic(err) } // Use configuration... } ``` -------------------------------- ### NewBaseClient Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/media.md Creates a new stateless media client. This client is used to perform various media operations. ```APIDOC ## NewBaseClient ### Description Creates a new stateless media client. ### Parameters - **confReader** (`config.Reader`): Configuration reader. - **sender** (`whttp.AnySender`): HTTP sender. ### Returns - `*BaseClient`: Initialized media client. ### Example ```go mediaClient := media.NewBaseClient(reader, httpSender) ``` ``` -------------------------------- ### Configure and Validate Secure Requests Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Sets up a configuration object for secure requests, including essential details like BaseURL, API version, access token, and AppSecret. It then validates this configuration. ```go conf := &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: token, PhoneNumberID: phoneID, BusinessAccountID: wabaID, AppSecret: "your_app_secret", // Required SecureRequests: true, } if err := config.Validate(conf); err != nil { log.Fatal(err) } ``` -------------------------------- ### Set up Two-Step Verification Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Use this method to set up two-step verification for a phone number by providing a 6-digit code, phone number ID, and access token. ```go response, err := twoStepClient.TwoStepVerification(ctx, &auth.TwoStepVerificationRequest{ SixDigitCode: "123456", PhoneNumberID: "123456789", AccessToken: "token123", }) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Avoid Hardcoding Secrets in Go Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Demonstrates the difference between hardcoding sensitive tokens and retrieving them from environment variables for better security. ```go // ❌ Bad token := "Bearer eaac..." // ✅ Good token := os.Getenv("WHATSAPP_TOKEN") ``` -------------------------------- ### Creating and Sending a Message Request Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Constructs a POST request to send a message and configures the response decoder, including error inspection. ```go req := &whttp.Request[message.Message]{ Type: whttp.RequestTypeSendMessage, BaseURL: "https://graph.facebook.com", Bearer: accessToken, Method: http.MethodPost, Endpoints: []string{"v24.0", phoneID, "messages"}, Headers: map[string]string{"Content-Type": "application/json"}, Message: messageObj, } response := &message.Response{} decoder := whttp.ResponseDecoderJSON(response, whttp.DecodeOptions{ DisallowUnknownFields: false, DisallowEmptyResponse: true, InspectResponseError: true, }) err := sender.Send(ctx, req, decoder) ``` -------------------------------- ### SetupTwoStepVerification Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Sets up two-step verification for a phone number. Requires a 6-digit PIN and an API access token. ```APIDOC ## SetupTwoStepVerification ### Description Sets up two-step verification for a phone number. This involves providing a 6-digit PIN code and an API access token. ### Method POST ### Endpoint /v1/verify ### Parameters #### Request Body - **SixDigitCode** (string) - Yes - 6-digit PIN code - **PhoneNumberID** (string) - Yes - Phone number ID - **AccessToken** (string) - Yes - API access token ### Request Example ```json { "SixDigitCode": "string", "PhoneNumberID": "string", "AccessToken": "string" } ``` ### Response #### Success Response (200) - **Success** (bool) - Whether operation succeeded #### Response Example ```json { "Success": true } ``` ``` -------------------------------- ### NewClient Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/message-client.md Creates a new stateful message client. This function initializes a client with context, configuration reader, an HTTP sender, and optional middlewares. ```APIDOC ## NewClient ### Description Creates a new stateful message client. This function initializes a client with context, configuration reader, an HTTP sender, and optional middlewares. ### Signature ```go func NewClient( ctx context.Context, reader config.Reader, sender whttp.Sender[Message], middlewares ...SenderMiddleware, ) (*Client, error) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **ctx** (`context.Context`) - Required - Context for initialization - **reader** (`config.Reader`) - Required - Configuration reader - **sender** (`whttp.Sender[Message]`) - Required - HTTP message sender - **middlewares** (`...SenderMiddleware`) - Optional - Request/response middlewares ### Returns - `(*Client, error)`: Initialized client or error ### Throws - **read config error**: Configuration reader fails ### Example ```go reader := config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { return &config.Config{ BaseURL: "https://graph.facebook.com", APIVersion: "v24.0", AccessToken: "token123", PhoneNumberID: "12345", BusinessAccountID: "67890", }, nil }) coreClient := whttp.NewSender[message.Message]() coreClient.SetHTTPClient(http.DefaultClient) client, err := message.NewClient(ctx, reader, coreClient) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Load Configuration from Kubernetes ConfigMap in Go Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Illustrates how to read configuration from a Kubernetes ConfigMap mounted as a file and unmarshal it into a config struct. ```go func getConfigFromK8s(ctx context.Context) (*config.Config, error) { ns := "default" name := "whatsapp-config" // Read from mounted configmap data, err := ioutil.ReadFile(fmt.Sprintf("/var/run/config/%s", name)) if err != nil { return nil, err } var cfg config.Config return &cfg, json.Unmarshal(data, &cfg) } ``` -------------------------------- ### Client SendAudio Method Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/message-client.md Sends an audio message using either a URL or a media ID. ```go func (c *Client) SendAudio(ctx context.Context, request *Request[Audio]) (*Response, error) ``` -------------------------------- ### Generate and Manage QR Codes Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/flows-qrcode.md Shows how to generate a QR code for WhatsApp, save the image, and retrieve information about the QR code's expiration. ```go qrService := qrcode.NewService(reader, sender) // Generate QR code response, err := qrService.GenerateQRCode(ctx, phoneNumberID, &qrcode.QRCodeRequest{ Format: "PNG", Size: 256, }) // Save QR code image išt.WriteFile("qrcode.png", response.Code, 0644) // Get QR code info info, err := qrService.GetQRCodeInfo(ctx, response.Code) fmt.Printf("Expires at: %v\n", time.Unix(info.ExpiresAt, 0)) ``` -------------------------------- ### Reuse HTTP Client Instance Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Reuse a single http.Client instance across multiple sender initializations to benefit from connection pooling and reduce overhead. This is the recommended approach for performance. ```go client := &http.Client{Timeout: 30 * time.Second} sender1 := whttp.NewSender[T](whttp.WithCoreClientHTTPClient(client)) sender2 := whttp.NewSender[T](whttp.WithCoreClientHTTPClient(client)) ``` -------------------------------- ### Load Configuration from JSON File Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/configuration.md Parses a JSON file to load WhatsApp API configuration. The file structure should match the expected `FileConfig` type. Use this when configuration is stored externally in a structured format. ```go type FileConfig struct { WhatsApp struct { BaseURL string `json:"base_url"` APIVersion string `json:"api_version"` AccessToken string `json:"access_token"` PhoneNumberID string `json:"phone_number_id"` BusinessAccountID string `json:"business_account_id"` AppSecret string `json:"app_secret,omitempty"` AppID string `json:"app_id,omitempty"` SecureRequests bool `json:"secure_requests,omitempty"` DebugLogLevel string `json:"debug_log_level,omitempty"` } `json:"whatsapp"` } func NewConfigReader(configPath string) config.Reader { return config.ReaderFunc(func(ctx context.Context) (*config.Config, error) { data, err := ioutil.ReadFile(configPath) if err != nil { return nil, err } var fileConfig FileConfig if err := json.Unmarshal(data, &fileConfig); err != nil { return nil, err } return &config.Config{ BaseURL: fileConfig.WhatsApp.BaseURL, APIVersion: fileConfig.WhatsApp.APIVersion, AccessToken: fileConfig.WhatsApp.AccessToken, PhoneNumberID: fileConfig.WhatsApp.PhoneNumberID, BusinessAccountID: fileConfig.WhatsApp.BusinessAccountID, AppSecret: fileConfig.WhatsApp.AppSecret, AppID: fileConfig.WhatsApp.AppID, SecureRequests: fileConfig.WhatsApp.SecureRequests, DebugLogLevel: fileConfig.WhatsApp.DebugLogLevel, }, nil }) } ``` ```json { "whatsapp": { "base_url": "https://graph.facebook.com", "api_version": "v24.0", "access_token": "your_token_here", "phone_number_id": "123456789", "business_account_id": "abcdef123", "app_secret": "", "app_id": "", "secure_requests": false, "debug_log_level": "" } } ``` -------------------------------- ### Read and Validate Configuration from Reader Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/config.md Use this function to read configuration directly from a Reader and validate it simultaneously. Handles errors during reading or validation. ```Go conf, err := config.ReadValidate(ctx, reader) if err != nil { fmt.Printf("Failed to read and validate config: %v\n", err) } ``` -------------------------------- ### NewClient Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/auth.md Creates a new authentication client instance with the specified base URL, API version, and HTTP sender. ```APIDOC ## NewClient ### Description Creates a new authentication client. ### Signature ```go func NewClient(baseURL, apiVersion string, sender whttp.AnySender) *Client ``` ### Parameters #### Path Parameters - **baseURL** (string) - Required - API base URL - **apiVersion** (string) - Required - API version (e.g., "v24.0") - **sender** (`whttp.AnySender`) - Required - HTTP sender ### Returns - `*Client`: Initialized auth client ### Example ```go httpSender := whttp.NewSender[any]() httpSender.SetHTTPClient(http.DefaultClient) authClient := auth.NewClient( "https://graph.facebook.com", "v24.0", httpSender, ) ``` ``` -------------------------------- ### Set HTTP Client Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/http-layer.md Configures the underlying `*http.Client` to be used for making requests. ```go func (core *CoreClient[T]) SetHTTPClient(httpClient *http.Client) ``` -------------------------------- ### BaseClient Structure Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/media.md Represents a base client for interacting with services. It holds configuration and sender components. ```go type BaseClient struct { ConfReader config.Reader // Configuration reader Sender whttp.AnySender // HTTP sender } ``` -------------------------------- ### NewBaseClient Source: https://github.com/piusalfred/whatsapp/blob/main/_autodocs/api-reference/message-client.md Creates a new stateless message client. This function initializes a client using an HTTP sender and a configuration reader. ```APIDOC ## NewBaseClient ### Description Creates a new stateless message client. This function initializes a client using an HTTP sender and a configuration reader. ### Signature ```go func NewBaseClient( sender whttp.Sender[Message], reader config.Reader, ) (*BaseClient, error) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **sender** (`whttp.Sender[Message]`) - Required - HTTP message sender - **reader** (`config.Reader`) - Required - Configuration reader ### Returns - `(*BaseClient, error)`: Initialized client or error ### Example ```go coreClient := whttp.NewSender[message.Message]() baseClient, err := message.NewBaseClient(coreClient, reader) if err != nil { log.Fatal(err) } ``` ```