Go SDK

The official Go SDK for Posthawk. Zero external dependencies — built entirely on Go's standard library.

SDKInstallation

Add posthawk-go to your Go module:

Example

bash
go get github.com/endibuka/posthawk-go
SDKQuick Start

Create a client and send your first email:

Example

go
package main

import (
    "context"
    "fmt"
    "log"

    posthawk "github.com/endibuka/posthawk-go"
)

func main() {
    client := posthawk.New("ck_live_...")

    result, err := client.Emails.Send(context.Background(), &posthawk.SendEmailRequest{
        From:    "hi@yourdomain.com",
        To:      []string{"user@example.com"},
        Subject: "Hello from Posthawk",
        HTML:    "<h1>Welcome!</h1><p>Your account is ready.</p>",
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Sent! Job ID:", result.JobID)
}
SDKSend Email

The SendEmailRequest struct supports all email fields: | Field | Type | Required | Description | |---|---|---|---| | From | string | Yes | Sender email address | | To | []string | Yes | Recipient email addresses | | Subject | string | Yes | Email subject line | | HTML | string | No | HTML body | | Text | string | No | Plain text body | | Cc | []string | No | CC recipients | | Bcc | []string | No | BCC recipients | | ReplyTo | string | No | Reply-to address | | TemplateID | string | No | Template identifier | | Variables | map[string]string | No | Template variables | | Headers | map[string]string | No | Custom email headers | | ScheduledFor | string | No | RFC 3339 send time | | Timezone | string | No | IANA timezone | | Metadata | map[string]any | No | Custom metadata | | Tags | map[string]any | No | Email tags |

Example

go
result, err := client.Emails.Send(ctx, &posthawk.SendEmailRequest{
    From:    "hi@yourdomain.com",
    To:      []string{"alice@example.com", "bob@example.com"},
    Cc:      []string{"manager@example.com"},
    Subject: "Weekly Report",
    HTML:    "<h1>Report</h1>",
    Text:    "Plain text fallback",
    Headers: map[string]string{"X-Custom": "value"},
    Metadata: map[string]any{"campaign": "onboarding"},
    Tags:     map[string]any{"type": "transactional"},
})
SDKCheck Delivery Status

Poll the status of a sent email by job ID. Status values: pending, processing, completed, failed.

Example

go
status, err := client.Emails.Get(ctx, "job-id-here")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Status:", status.Status)     // pending | processing | completed | failed
fmt.Println("Created:", status.CreatedAt)
SDKList Scheduled Emails

Retrieve scheduled emails with optional filters:

Example

go
limit := 10
list, err := client.Scheduled.List(ctx, &posthawk.ListScheduledParams{
    Status: "scheduled",
    Limit:  &limit,
})
if err != nil {
    log.Fatal(err)
}

for _, email := range list.Data {
    fmt.Printf("%s → %s\n", email.Subject, email.ScheduledFor)
}
fmt.Println("Total:", list.Total)
SDKGet Scheduled Email

Retrieve a single scheduled email by ID:

Example

go
result, err := client.Scheduled.Get(ctx, "scheduled-email-id")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Subject:", result.Data.Subject)
fmt.Println("Scheduled for:", result.Data.ScheduledFor)
fmt.Println("Status:", result.Data.Status)
SDKCancel Scheduled Email

Cancel a scheduled email before it sends:

Example

go
result, err := client.Scheduled.Cancel(ctx, "scheduled-email-id")
if err != nil {
    log.Fatal(err)
}

fmt.Println(result.Message) // "Scheduled email cancelled"
SDKReschedule Email

Change the send time of a scheduled email:

Example

go
result, err := client.Scheduled.Reschedule(ctx, "scheduled-email-id", &posthawk.RescheduleRequest{
    ScheduledFor: "2026-04-01T10:00:00Z",
})
if err != nil {
    log.Fatal(err)
}

fmt.Println("New time:", result.Data.ScheduledFor)
SDKError Handling

All methods return Go's standard (T, error) tuples. Errors are of type *posthawk.Error with StatusCode and Message fields. Use errors.As for type assertion:

Example

go
result, err := client.Emails.Send(ctx, &posthawk.SendEmailRequest{
    From:    "hi@yourdomain.com",
    To:      []string{"user@example.com"},
    Subject: "Test",
    HTML:    "<p>Hello</p>",
})
if err != nil {
    var posthawkErr *posthawk.Error
    if errors.As(err, &posthawkErr) {
        fmt.Printf("API error %d: %s\n", posthawkErr.StatusCode, posthawkErr.Message)
    } else {
        fmt.Printf("Unexpected error: %v\n", err)
    }
    return
}

fmt.Println("Success:", result.JobID)
SDKDomain Management

Manage sending domains programmatically — add, verify, enable inbound receiving, configure webhooks, and set sending limits:

Example

go
// Add a domain
domain, err := client.Domains.Create(ctx, &posthawk.CreateDomainRequest{
    Domain: "mail.customer.com",
    Region: "us-east-1",
})
// domain.Data.DnsRecords → DNS records to configure

// List all domains
domains, err := client.Domains.List(ctx)

// Trigger verification check
status, err := client.Domains.Verify(ctx, "domain-uuid")
// status.Data.SendingEnabled → true when verified

// Enable inbound receiving
client.Domains.EnableReceiving(ctx, "domain-uuid")

// Set a webhook for inbound emails
client.Domains.UpdateWebhook(ctx, "domain-uuid", &posthawk.UpdateDomainWebhookRequest{
    WebhookURL: strPtr("https://yourapp.com/api/incoming-email"),
})

// Test the webhook
client.Domains.TestWebhook(ctx, "domain-uuid")

// Set per-domain sending limits
client.Domains.UpdateLimits(ctx, "domain-uuid", &posthawk.UpdateDomainLimitsRequest{
    MaxDailyEmails:   intPtr(1000),
    MaxMonthlyEmails: intPtr(25000),
})

// Remove limits (nil = unlimited)
client.Domains.UpdateLimits(ctx, "domain-uuid", &posthawk.UpdateDomainLimitsRequest{
    MaxDailyEmails:   nil,
    MaxMonthlyEmails: nil,
})

// Delete a domain
client.Domains.Delete(ctx, "domain-uuid")
SDKSelf-Hosted Configuration

Point the SDK at your own Posthawk instance using WithBaseURL. You can also provide a custom http.Client:

Example

go
// Custom base URL for self-hosted
client := posthawk.New("ck_live_...",
    posthawk.WithBaseURL("https://api.yourdomain.com"),
)

// Custom HTTP client with timeout
client := posthawk.New("ck_live_...",
    posthawk.WithHTTPClient(&http.Client{
        Timeout: 10 * time.Second,
    }),
)