Documentation
¶
Overview ¶
Package posthook provides a Go client library for the Posthook API.
Posthook is a webhook scheduling and delivery platform. This SDK allows you to schedule, manage, and verify webhook deliveries from your Go applications.
Usage ¶
client, err := posthook.NewClient("pk_...")
if err != nil {
log.Fatal(err)
}
// Schedule a hook with a relative delay
hook, resp, err := client.Hooks.Schedule(ctx, &posthook.HookScheduleParams{
Path: "/webhooks/user-created",
PostIn: "5m",
Data: map[string]any{"userId": "123"},
})
Authentication ¶
Pass your API key directly to NewClient, or set the POSTHOOK_API_KEY environment variable and pass an empty string:
client, err := posthook.NewClient("") // uses POSTHOOK_API_KEY
Verifying Webhook Signatures ¶
When receiving deliveries, use the Signatures service to verify authenticity:
client, _ := posthook.NewClient("pk_...", posthook.WithSigningKey("ph_sk_..."))
delivery, err := client.Signatures.ParseDelivery(body, r.Header)
Index ¶
- Constants
- func Bool(v bool) *bool
- type AuthenticationError
- type BadRequestError
- type BulkActionByFilter
- type BulkActionByIDs
- type BulkActionResult
- type BulkActions
- func (b *BulkActions) Cancel(ctx context.Context, params *BulkActionByIDs) (*BulkActionResult, *Response, error)
- func (b *BulkActions) CancelByFilter(ctx context.Context, params *BulkActionByFilter) (*BulkActionResult, *Response, error)
- func (b *BulkActions) Replay(ctx context.Context, params *BulkActionByIDs) (*BulkActionResult, *Response, error)
- func (b *BulkActions) ReplayByFilter(ctx context.Context, params *BulkActionByFilter) (*BulkActionResult, *Response, error)
- func (b *BulkActions) Retry(ctx context.Context, params *BulkActionByIDs) (*BulkActionResult, *Response, error)
- func (b *BulkActions) RetryByFilter(ctx context.Context, params *BulkActionByFilter) (*BulkActionResult, *Response, error)
- type Client
- type ConnectionError
- type Delivery
- type Error
- type ForbiddenError
- type Hook
- type HookListAllParams
- type HookListParams
- type HookRetryOverride
- type HookScheduleParams
- type HookSequenceData
- type HooksService
- func (s *HooksService) Bulk() *BulkActions
- func (s *HooksService) Delete(ctx context.Context, id string) (*Response, error)
- func (s *HooksService) Get(ctx context.Context, id string) (*Hook, *Response, error)
- func (s *HooksService) List(ctx context.Context, params *HookListParams) ([]*Hook, *Response, error)
- func (s *HooksService) ListAll(ctx context.Context, params *HookListAllParams) iter.Seq2[*Hook, error]
- func (s *HooksService) Schedule(ctx context.Context, params *HookScheduleParams) (*Hook, *Response, error)
- type InternalServerError
- type NotFoundError
- type Option
- type PayloadTooLargeError
- type QuotaInfo
- type RateLimitError
- type Response
- type SignatureVerificationError
- type SignaturesService
- type VerifyOption
Examples ¶
Constants ¶
const ( StatusPending = "pending" // Hooks awaiting delivery (includes dispatching and retry). StatusRetry = "retry" // Hooks waiting to be retried after a failed attempt. StatusCompleted = "completed" // Hooks that were delivered successfully. StatusFailed = "failed" // Hooks that exhausted all retry attempts. )
Hook status values for use with HookListParams.Status.
const ( SortByPostAt = "postAt" SortByCreatedAt = "createdAt" )
Sort field values for use with HookListParams.SortBy.
const ( SortOrderAsc = "ASC" SortOrderDesc = "DESC" )
Sort order values for use with HookListParams.SortOrder.
const ( StrategyFixed = "fixed" StrategyExponential = "exponential" )
Retry strategy values for use with HookRetryOverride.Strategy.
const Version = "1.0.0"
Version is the semantic version of this SDK.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AuthenticationError ¶
type AuthenticationError struct{ Err *Error }
AuthenticationError is returned for HTTP 401 responses.
func (*AuthenticationError) Error ¶
func (e *AuthenticationError) Error() string
func (*AuthenticationError) Unwrap ¶
func (e *AuthenticationError) Unwrap() error
type BadRequestError ¶
type BadRequestError struct{ Err *Error }
BadRequestError is returned for HTTP 400 responses.
func (*BadRequestError) Error ¶
func (e *BadRequestError) Error() string
func (*BadRequestError) Unwrap ¶
func (e *BadRequestError) Unwrap() error
type BulkActionByFilter ¶
type BulkActionByFilter struct {
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
EndpointKey string `json:"endpointKey,omitempty"`
SequenceID string `json:"sequenceID,omitempty"`
Limit int `json:"limit,omitempty"`
}
BulkActionByFilter specifies hooks to act on using a time range filter.
type BulkActionByIDs ¶
type BulkActionByIDs struct {
HookIDs []string `json:"hookIDs"`
}
BulkActionByIDs specifies hooks to act on by their individual IDs.
type BulkActionResult ¶
type BulkActionResult struct {
Affected int `json:"affected"`
}
BulkActionResult contains the result of a bulk action.
type BulkActions ¶
type BulkActions struct {
// contains filtered or unexported fields
}
BulkActions provides methods for performing bulk operations on hooks.
func (*BulkActions) Cancel ¶
func (b *BulkActions) Cancel(ctx context.Context, params *BulkActionByIDs) (*BulkActionResult, *Response, error)
Cancel cancels pending hooks specified by their IDs.
func (*BulkActions) CancelByFilter ¶
func (b *BulkActions) CancelByFilter(ctx context.Context, params *BulkActionByFilter) (*BulkActionResult, *Response, error)
CancelByFilter cancels pending hooks matching a time range filter.
func (*BulkActions) Replay ¶
func (b *BulkActions) Replay(ctx context.Context, params *BulkActionByIDs) (*BulkActionResult, *Response, error)
Replay re-delivers completed hooks specified by their IDs.
func (*BulkActions) ReplayByFilter ¶
func (b *BulkActions) ReplayByFilter(ctx context.Context, params *BulkActionByFilter) (*BulkActionResult, *Response, error)
ReplayByFilter re-delivers completed hooks matching a time range filter.
func (*BulkActions) Retry ¶
func (b *BulkActions) Retry(ctx context.Context, params *BulkActionByIDs) (*BulkActionResult, *Response, error)
Retry re-attempts delivery for failed hooks specified by their IDs.
func (*BulkActions) RetryByFilter ¶
func (b *BulkActions) RetryByFilter(ctx context.Context, params *BulkActionByFilter) (*BulkActionResult, *Response, error)
RetryByFilter re-attempts delivery for failed hooks matching a time range filter.
type Client ¶
type Client struct {
// Hooks provides access to hook scheduling and management endpoints.
Hooks *HooksService
// Signatures provides webhook signature verification.
Signatures *SignaturesService
// contains filtered or unexported fields
}
Client manages communication with the Posthook API. A Client is safe for concurrent use by multiple goroutines.
func NewClient ¶
NewClient creates a new Posthook API client. If apiKey is empty, it falls back to the POSTHOOK_API_KEY environment variable. Returns an error if no API key is available.
Example ¶
package main
import (
posthook "github.com/posthook/posthook-go"
)
func main() {
client, err := posthook.NewClient("pk_...")
if err != nil {
panic(err)
}
_ = client // use client to schedule hooks, verify signatures, etc.
}
type ConnectionError ¶
type ConnectionError struct{ Err *Error }
ConnectionError is returned for network or timeout errors.
func (*ConnectionError) Error ¶
func (e *ConnectionError) Error() string
func (*ConnectionError) Unwrap ¶
func (e *ConnectionError) Unwrap() error
type Delivery ¶
type Delivery struct {
HookID string `json:"hookId"`
Timestamp int64 `json:"timestamp"`
Path string `json:"path"`
Data json.RawMessage `json:"data"`
PostAt time.Time `json:"postAt"`
PostedAt time.Time `json:"postedAt"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
// Body contains the raw HTTP request body bytes. It is not included
// in JSON serialization and is provided for caller convenience.
Body []byte `json:"-"`
}
Delivery is the parsed result of a verified webhook delivery. It contains the hook metadata extracted from headers and the parsed delivery body.
type Error ¶
type Error struct {
StatusCode int `json:"statusCode"`
Code string `json:"code"`
Message string `json:"message"`
}
Error is the base error type returned by the Posthook API.
type ForbiddenError ¶
type ForbiddenError struct{ Err *Error }
ForbiddenError is returned for HTTP 403 responses.
func (*ForbiddenError) Error ¶
func (e *ForbiddenError) Error() string
func (*ForbiddenError) Unwrap ¶
func (e *ForbiddenError) Unwrap() error
type Hook ¶
type Hook struct {
ID string `json:"id"`
Path string `json:"path"`
Domain *string `json:"domain,omitempty"`
Data json.RawMessage `json:"data"`
PostAt time.Time `json:"postAt"`
Status string `json:"status"`
PostDurationSeconds float64 `json:"postDurationSeconds"`
Attempts int `json:"attempts,omitempty"`
FailureError string `json:"failureError,omitempty"`
SequenceData *HookSequenceData `json:"sequenceData,omitempty"`
RetryOverride *HookRetryOverride `json:"retryOverride,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Hook represents a scheduled webhook.
type HookListAllParams ¶
type HookListAllParams struct {
// Status filters hooks by status (e.g., StatusFailed).
Status string
// PostAtAfter is the start cursor: only return hooks scheduled after this time (exclusive).
PostAtAfter time.Time
// PageSize is the number of hooks to fetch per page (default 100, max 1000).
PageSize int
}
HookListAllParams contains the parameters for auto-paginating hook listing. Uses cursor-based pagination via postAt ordering.
type HookListParams ¶
type HookListParams struct {
Status string
Limit int
Offset int
PostAtBefore time.Time
PostAtAfter time.Time
CreatedAtBefore time.Time
CreatedAtAfter time.Time
SortBy string
SortOrder string
}
HookListParams contains the query parameters for listing hooks. All fields are optional; zero values are ignored.
type HookRetryOverride ¶
type HookRetryOverride struct {
MinRetries int `json:"minRetries"`
DelaySecs int `json:"delaySecs"`
Strategy string `json:"strategy"`
BackoffFactor float64 `json:"backoffFactor,omitempty"`
MaxDelaySecs int `json:"maxDelaySecs,omitempty"`
Jitter *bool `json:"jitter,omitempty"`
}
HookRetryOverride configures per-hook retry behavior.
type HookScheduleParams ¶
type HookScheduleParams struct {
// Path is the endpoint path that will be appended to your project's domain.
Path string
// Data is the JSON payload to deliver. Accepts any JSON-serializable value.
Data any
// PostAt schedules delivery at an absolute UTC time.
PostAt time.Time
// PostAtLocal schedules delivery at a local time. Must be used with Timezone.
PostAtLocal string
// Timezone is the IANA timezone for PostAtLocal (e.g., "America/New_York").
Timezone string
// PostIn schedules delivery after a relative delay (e.g., "5m", "2h").
PostIn string
// RetryOverride configures per-hook retry behavior.
RetryOverride *HookRetryOverride
}
HookScheduleParams contains the parameters for scheduling a new hook. Exactly one of PostAt, PostAtLocal (with Timezone), or PostIn must be provided.
func (HookScheduleParams) MarshalJSON ¶
func (p HookScheduleParams) MarshalJSON() ([]byte, error)
MarshalJSON implements custom JSON marshaling that omits zero-value optional fields. This is needed because encoding/json's omitempty does not treat time.Time zero values as empty.
type HookSequenceData ¶
type HookSequenceData struct {
SequenceID string `json:"sequenceID"`
StepName string `json:"stepName"`
SequenceLastRunAt string `json:"sequenceLastRunAt"`
}
HookSequenceData contains sequence context for a hook that is part of a sequence.
type HooksService ¶
type HooksService service
HooksService handles communication with the hook-related endpoints of the Posthook API.
func (*HooksService) Bulk ¶
func (s *HooksService) Bulk() *BulkActions
Bulk returns a BulkActions handle for performing bulk operations on hooks.
func (*HooksService) Delete ¶
Delete removes a scheduled hook. It returns nil error on both 200 (deleted) and 404 (already delivered or gone) — a hook you're canceling may have already been delivered, and that's not an error.
func (*HooksService) List ¶
func (s *HooksService) List(ctx context.Context, params *HookListParams) ([]*Hook, *Response, error)
List retrieves a paginated list of hooks. Use Limit and Offset on HookListParams for pagination. When the returned slice is shorter than the requested Limit, you have reached the last page.
func (*HooksService) ListAll ¶
func (s *HooksService) ListAll(ctx context.Context, params *HookListAllParams) iter.Seq2[*Hook, error]
ListAll returns an iterator that yields every matching hook across all pages. It uses cursor-based pagination via postAt ordering for consistency.
Usage:
for hook, err := range client.Hooks.ListAll(ctx, &posthook.HookListAllParams{Status: posthook.StatusFailed}) {
if err != nil {
log.Fatal(err)
}
fmt.Println(hook.ID)
}
func (*HooksService) Schedule ¶
func (s *HooksService) Schedule(ctx context.Context, params *HookScheduleParams) (*Hook, *Response, error)
Schedule creates a new scheduled hook. Exactly one of PostAt, PostAtLocal (with Timezone), or PostIn must be set on params.
Example ¶
package main
import (
"context"
"fmt"
posthook "github.com/posthook/posthook-go"
)
func main() {
client, err := posthook.NewClient("pk_...")
if err != nil {
panic(err)
}
hook, _, err := client.Hooks.Schedule(context.Background(), &posthook.HookScheduleParams{
Path: "/webhooks/user-created",
PostIn: "5m",
Data: map[string]any{"userId": "123"},
})
if err != nil {
panic(err)
}
fmt.Println(hook.ID)
}
Example (PostAt) ¶
package main
import (
"context"
"fmt"
"time"
posthook "github.com/posthook/posthook-go"
)
func main() {
client, err := posthook.NewClient("pk_...")
if err != nil {
panic(err)
}
hook, _, err := client.Hooks.Schedule(context.Background(), &posthook.HookScheduleParams{
Path: "/webhooks/reminder",
PostAt: time.Now().Add(24 * time.Hour),
Data: map[string]any{"userId": "123"},
})
if err != nil {
panic(err)
}
fmt.Println(hook.ID)
}
type InternalServerError ¶
type InternalServerError struct{ Err *Error }
InternalServerError is returned for HTTP 5xx responses.
func (*InternalServerError) Error ¶
func (e *InternalServerError) Error() string
func (*InternalServerError) Unwrap ¶
func (e *InternalServerError) Unwrap() error
type NotFoundError ¶
type NotFoundError struct{ Err *Error }
NotFoundError is returned for HTTP 404 responses.
func (*NotFoundError) Error ¶
func (e *NotFoundError) Error() string
func (*NotFoundError) Unwrap ¶
func (e *NotFoundError) Unwrap() error
type Option ¶
Option configures a Client.
func WithBaseURL ¶
WithBaseURL sets a custom base URL for API requests.
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client for API requests.
func WithSigningKey ¶
WithSigningKey sets the signing key used for webhook signature verification.
func WithUserAgent ¶
WithUserAgent sets a custom User-Agent header for API requests.
type PayloadTooLargeError ¶
type PayloadTooLargeError struct{ Err *Error }
PayloadTooLargeError is returned for HTTP 413 responses.
func (*PayloadTooLargeError) Error ¶
func (e *PayloadTooLargeError) Error() string
func (*PayloadTooLargeError) Unwrap ¶
func (e *PayloadTooLargeError) Unwrap() error
type QuotaInfo ¶
type QuotaInfo struct {
Limit int `json:"limit"`
Usage int `json:"usage"`
Remaining int `json:"remaining"`
ResetsAt time.Time `json:"resetsAt"`
}
QuotaInfo contains hook quota information parsed from response headers.
type RateLimitError ¶
type RateLimitError struct{ Err *Error }
RateLimitError is returned for HTTP 429 responses.
func (*RateLimitError) Error ¶
func (e *RateLimitError) Error() string
func (*RateLimitError) Unwrap ¶
func (e *RateLimitError) Unwrap() error
type Response ¶
Response wraps the standard http.Response and includes Posthook-specific metadata such as quota information. Note that the response body has already been read and closed; do not attempt to read from it.
type SignatureVerificationError ¶
type SignatureVerificationError struct{ Err *Error }
SignatureVerificationError is returned when webhook signature verification fails.
func (*SignatureVerificationError) Error ¶
func (e *SignatureVerificationError) Error() string
func (*SignatureVerificationError) Unwrap ¶
func (e *SignatureVerificationError) Unwrap() error
type SignaturesService ¶
type SignaturesService struct {
// contains filtered or unexported fields
}
SignaturesService provides webhook signature verification.
func NewSignatures ¶
func NewSignatures(signingKey string) (*SignaturesService, error)
NewSignatures creates a standalone SignaturesService for verifying webhook signatures without needing a full Client or API key. This is useful when you only need to receive and verify webhooks, not schedule hooks.
If signingKey is empty, it falls back to the POSTHOOK_SIGNING_KEY environment variable. An error is returned if no signing key is available from either source.
sigs, err := posthook.NewSignatures("whsec_your_signing_key")
delivery, err := sigs.ParseDelivery(body, req.Header)
func (*SignaturesService) ParseDelivery ¶
func (s *SignaturesService) ParseDelivery(body []byte, headers http.Header, opts ...VerifyOption) (*Delivery, error)
ParseDelivery verifies the webhook signature from the provided headers and parses the delivery payload. It extracts the Posthook-Id, Posthook-Timestamp, and Posthook-Signature headers, validates the HMAC-SHA256 signature, and returns a parsed Delivery.
The body parameter should be the raw HTTP request body bytes.
Example ¶
package main
import (
"fmt"
"io"
"net/http"
posthook "github.com/posthook/posthook-go"
)
func main() {
client, err := posthook.NewClient("pk_...", posthook.WithSigningKey("ph_sk_..."))
if err != nil {
panic(err)
}
http.HandleFunc("/webhooks/test", func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
delivery, err := client.Signatures.ParseDelivery(body, r.Header)
if err != nil {
http.Error(w, "invalid signature", http.StatusUnauthorized)
return
}
fmt.Println(delivery.HookID, delivery.Path)
w.WriteHeader(http.StatusOK)
})
}
type VerifyOption ¶
type VerifyOption func(*verifyConfig)
VerifyOption configures signature verification behavior.
func WithTolerance ¶
func WithTolerance(d time.Duration) VerifyOption
WithTolerance sets the maximum age of a webhook signature. Signatures older than this duration are rejected. The default is 5 minutes.