Documentation
¶
Overview ¶
Package fulkruma is the official Go SDK for Fulkruma — stock, warehouses, shipping (Biteship), licenses, deliveries, API keys, audit log, billing, integrations status, stats, webhooks. Mirrors `@forjio/fulkruma-node` and `fulkruma` (Python) 1:1.
All API calls are HMAC-signed:
Authorization: Fulkruma-HMAC-SHA256 keyId=…, scope=*, signature=… X-Fulkruma-Timestamp: <unix> X-Fulkruma-On-Behalf-Of: <accountId> (platform-admin only, optional) Idempotency-Key: idem_<uuid> (on replay-sensitive mutations)
The signature payload is `${METHOD}\n${path}\n${ts}\n${sha256(body)}` — plus `\n${idempotencyKey}` when present.
Index ¶
- type APIKeyCreateInput
- type APIKeysResource
- type AddressCreateInput
- type AddressesResource
- type AdminResource
- func (r *AdminResource) GetWorkspace(ctx context.Context, accountID string) (*PartnerWorkspace, error)
- func (r *AdminResource) PartnerUsage(ctx context.Context, p PartnerUsageParams) (*PartnerUsageSummary, error)
- func (r *AdminResource) ProvisionWorkspace(ctx context.Context, in ProvisionWorkspaceInput) (*PartnerWorkspace, error)
- type ApiEnvelope
- type ArchivedEnvelope
- type AuditLogListParams
- type AuditLogListResult
- type AuditLogResource
- type BillingCheckoutInput
- type BillingCheckoutResult
- type BillingInvoicesParams
- type BillingInvoicesResult
- type BillingResource
- func (r *BillingResource) Cancel(ctx context.Context) (map[string]any, error)
- func (r *BillingResource) Checkout(ctx context.Context, in BillingCheckoutInput) (*BillingCheckoutResult, error)
- func (r *BillingResource) CurrentPlan(ctx context.Context) (map[string]any, error)
- func (r *BillingResource) Invoices(ctx context.Context, p BillingInvoicesParams) (*BillingInvoicesResult, error)
- func (r *BillingResource) Plans(ctx context.Context) ([]map[string]any, error)
- func (r *BillingResource) Subscription(ctx context.Context) (map[string]any, error)
- func (r *BillingResource) Usage(ctx context.Context) (map[string]any, error)
- type Client
- type ClientOptions
- type CustomerAddress
- type DeletedEnvelope
- type DeliveriesResource
- type Delivery
- type DeliveryCreateInput
- type EnvelopeMeta
- type Error
- type ErrorBody
- type IntegrationsResource
- type IntegrationsStatus
- type License
- type LicenseActivateInput
- type LicenseActivateResult
- type LicenseActivation
- type LicenseDeactivateResult
- type LicenseIssueInput
- type LicenseStatus
- type LicenseValidateParams
- type LicenseValidateResult
- type LicensesResource
- func (r *LicensesResource) Activate(ctx context.Context, in LicenseActivateInput) (*LicenseActivateResult, error)
- func (r *LicensesResource) Deactivate(ctx context.Context, in LicenseActivateInput) (*LicenseDeactivateResult, error)
- func (r *LicensesResource) Issue(ctx context.Context, in LicenseIssueInput) (*License, error)
- func (r *LicensesResource) List(ctx context.Context) ([]License, error)
- func (r *LicensesResource) Revoke(ctx context.Context, id string) (*License, error)
- func (r *LicensesResource) Validate(ctx context.Context, p LicenseValidateParams) (*LicenseValidateResult, error)
- type PartnerUsageMerchant
- type PartnerUsageParams
- type PartnerUsagePeriod
- type PartnerUsageSummary
- type PartnerUsageTotals
- type PartnerWorkspace
- type Product
- type ProductCreateInput
- type ProductEnvelope
- type ProductListEnvelope
- type ProductListParams
- type ProductType
- type ProductUpdateInput
- type ProductVariant
- type ProductsResource
- func (r *ProductsResource) AddVariant(ctx context.Context, productID string, in VariantCreateInput) (*ProductVariant, error)
- func (r *ProductsResource) Archive(ctx context.Context, id string) (bool, error)
- func (r *ProductsResource) ArchiveVariant(ctx context.Context, productID, variantID string) (bool, error)
- func (r *ProductsResource) Create(ctx context.Context, in ProductCreateInput) (*Product, error)
- func (r *ProductsResource) Get(ctx context.Context, id string) (*Product, error)
- func (r *ProductsResource) List(ctx context.Context, p ProductListParams) ([]Product, error)
- func (r *ProductsResource) Update(ctx context.Context, id string, patch ProductUpdateInput) (*Product, error)
- func (r *ProductsResource) UpdateVariant(ctx context.Context, productID, variantID string, patch VariantUpdateInput) (*ProductVariant, error)
- type ProvisionWorkspaceInput
- type RequestOptions
- type RevokedEnvelope
- type Shipment
- type ShipmentCreateInput
- type ShipmentStatus
- type ShipmentsResource
- type ShippingRatesInput
- type ShippingResource
- func (r *ShippingResource) Couriers(ctx context.Context) ([]map[string]any, error)
- func (r *ShippingResource) Origin(ctx context.Context) (map[string]any, error)
- func (r *ShippingResource) Rates(ctx context.Context, in ShippingRatesInput) (map[string]any, error)
- func (r *ShippingResource) SetOrigin(ctx context.Context, in map[string]any) (map[string]any, error)
- type StatsOverview
- type StatsResource
- type StockAdjustInput
- type StockAdjustResult
- type StockMovement
- type StockMovementReason
- type StockReservation
- type StockResource
- func (r *StockResource) Adjust(ctx context.Context, in StockAdjustInput) (*StockAdjustResult, error)
- func (r *StockResource) Levels(ctx context.Context, variantID string) ([]VariantStock, error)
- func (r *StockResource) Movements(ctx context.Context, variantID string) ([]StockMovement, error)
- func (r *StockResource) Reservations(ctx context.Context) ([]StockReservation, error)
- type VariantCreateInput
- type VariantEnvelope
- type VariantStock
- type VariantStockWarehouseRef
- type VariantUpdateInput
- type VerifyWebhookOptions
- type Warehouse
- type WarehouseCreateInput
- type WarehouseUpdateInput
- type WarehousesResource
- func (r *WarehousesResource) Archive(ctx context.Context, id string) (bool, error)
- func (r *WarehousesResource) Create(ctx context.Context, in WarehouseCreateInput) (*Warehouse, error)
- func (r *WarehousesResource) List(ctx context.Context) ([]Warehouse, error)
- func (r *WarehousesResource) Update(ctx context.Context, id string, patch WarehouseUpdateInput) (*Warehouse, error)
- type WebhookEndpointCreateInput
- type WebhookEndpointUpdateInput
- type WebhookEventEnvelope
- type WebhookEventsListParams
- type WebhookEventsListResult
- type WebhooksResource
- func (r *WebhooksResource) CreateEndpoint(ctx context.Context, in WebhookEndpointCreateInput) (map[string]any, error)
- func (r *WebhooksResource) DeleteEndpoint(ctx context.Context, id string) (bool, error)
- func (r *WebhooksResource) ListEndpoints(ctx context.Context) ([]map[string]any, error)
- func (r *WebhooksResource) ListEvents(ctx context.Context, p WebhookEventsListParams) (*WebhookEventsListResult, error)
- func (r *WebhooksResource) UpdateEndpoint(ctx context.Context, id string, patch WebhookEndpointUpdateInput) (map[string]any, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIKeyCreateInput ¶
type APIKeyCreateInput struct {
Description string `json:"description,omitempty"`
Scope string `json:"scope,omitempty"`
}
APIKeyCreateInput — POST /api/v1/api-keys body.
type APIKeysResource ¶
type APIKeysResource struct {
// contains filtered or unexported fields
}
APIKeysResource — /api/v1/api-keys.
func (*APIKeysResource) Create ¶
func (r *APIKeysResource) Create(ctx context.Context, in APIKeyCreateInput) (map[string]any, error)
Create — POST /api/v1/api-keys (idempotent).
type AddressCreateInput ¶
type AddressCreateInput struct {
CustomerID string `json:"customerId"`
Label string `json:"label"`
ContactName string `json:"contactName"`
ContactPhone string `json:"contactPhone"`
Email string `json:"email,omitempty"`
Address string `json:"address"`
PostalCode string `json:"postalCode,omitempty"`
AreaID string `json:"areaId,omitempty"`
Lat *float64 `json:"lat,omitempty"`
Lng *float64 `json:"lng,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
}
AddressCreateInput — POST /api/v1/addresses body.
type AddressesResource ¶
type AddressesResource struct {
// contains filtered or unexported fields
}
AddressesResource — /api/v1/addresses.
func (*AddressesResource) Create ¶
func (r *AddressesResource) Create(ctx context.Context, in AddressCreateInput) (*CustomerAddress, error)
Create — POST /api/v1/addresses.
func (*AddressesResource) List ¶
func (r *AddressesResource) List(ctx context.Context, customerID string) ([]CustomerAddress, error)
List — GET /api/v1/addresses.
type AdminResource ¶
type AdminResource struct {
// contains filtered or unexported fields
}
AdminResource — /api/v1/admin/* (platform-admin scope only).
func (*AdminResource) GetWorkspace ¶
func (r *AdminResource) GetWorkspace(ctx context.Context, accountID string) (*PartnerWorkspace, error)
GetWorkspace — GET /api/v1/admin/workspaces/:accountId.
func (*AdminResource) PartnerUsage ¶
func (r *AdminResource) PartnerUsage(ctx context.Context, p PartnerUsageParams) (*PartnerUsageSummary, error)
PartnerUsage — GET /api/v1/admin/partner/usage.
func (*AdminResource) ProvisionWorkspace ¶
func (r *AdminResource) ProvisionWorkspace(ctx context.Context, in ProvisionWorkspaceInput) (*PartnerWorkspace, error)
ProvisionWorkspace — POST /api/v1/admin/workspaces. Idempotency key is derived deterministically (`ws_<accountId>_<partner>`), matching the Node SDK so the same input always yields the same key.
type ApiEnvelope ¶
type ApiEnvelope struct {
Data json.RawMessage `json:"data"`
Error *ErrorBody `json:"error"`
Meta *EnvelopeMeta `json:"meta,omitempty"`
}
ApiEnvelope mirrors the backend's standard `{ data, error, meta }` JSON shape. Generic-free on purpose — every resource method unmarshals `Data` into a concrete struct.
type ArchivedEnvelope ¶
type ArchivedEnvelope struct {
Archived bool `json:"archived"`
}
ArchivedEnvelope wraps `{ archived: bool }` responses.
type AuditLogListParams ¶
AuditLogListParams — GET /audit-log query.
type AuditLogListResult ¶
type AuditLogListResult struct {
Entries []map[string]any `json:"entries"`
NextCursor string `json:"nextCursor,omitempty"`
}
AuditLogListResult mirrors the cursor-paginated envelope.
type AuditLogResource ¶
type AuditLogResource struct {
// contains filtered or unexported fields
}
AuditLogResource — /api/v1/audit-log.
func (*AuditLogResource) List ¶
func (r *AuditLogResource) List(ctx context.Context, p AuditLogListParams) (*AuditLogListResult, error)
List — GET /api/v1/audit-log.
type BillingCheckoutInput ¶
type BillingCheckoutInput struct {
PlanID string `json:"planId"`
SuccessURL string `json:"successUrl,omitempty"`
CancelURL string `json:"cancelUrl,omitempty"`
}
BillingCheckoutInput — POST /billing/checkout body.
type BillingCheckoutResult ¶
BillingCheckoutResult mirrors `{ url, sessionId }`.
type BillingInvoicesParams ¶
BillingInvoicesParams — GET /billing/invoices query.
type BillingInvoicesResult ¶
type BillingInvoicesResult struct {
Invoices []map[string]any `json:"invoices"`
NextCursor string `json:"nextCursor,omitempty"`
}
BillingInvoicesResult mirrors the paginated envelope.
type BillingResource ¶
type BillingResource struct {
// contains filtered or unexported fields
}
BillingResource — /api/v1/billing/*.
func (*BillingResource) Checkout ¶
func (r *BillingResource) Checkout(ctx context.Context, in BillingCheckoutInput) (*BillingCheckoutResult, error)
Checkout — POST /billing/checkout.
func (*BillingResource) CurrentPlan ¶
CurrentPlan — GET /billing/plan.
func (*BillingResource) Invoices ¶
func (r *BillingResource) Invoices(ctx context.Context, p BillingInvoicesParams) (*BillingInvoicesResult, error)
Invoices — GET /billing/invoices.
func (*BillingResource) Subscription ¶
Subscription — GET /billing/subscription.
type Client ¶
type Client struct {
// Resource namespaces — match the Node SDK property names.
Products *ProductsResource
Warehouses *WarehousesResource
Stock *StockResource
Addresses *AddressesResource
Shipments *ShipmentsResource
Shipping *ShippingResource
Licenses *LicensesResource
Deliveries *DeliveriesResource
APIKeys *APIKeysResource
AuditLog *AuditLogResource
Billing *BillingResource
Integrations *IntegrationsResource
Stats *StatsResource
Webhooks *WebhooksResource
Admin *AdminResource
// contains filtered or unexported fields
}
Client is the HMAC-signed Fulkruma REST client. Construct one per merchant (or one platform-admin client and call ForMerchant per call site).
func NewClient ¶
func NewClient(opts ClientOptions) (*Client, error)
NewClient constructs a Fulkruma client. Returns *Error when required fields are missing — never panics.
func (*Client) ForMerchant ¶
ForMerchant returns a shallow clone scoped to a specific merchant. Only useful with platform-admin keys.
func (*Client) Request ¶
func (c *Client) Request(ctx context.Context, method, path string, body any, out any, opts *RequestOptions) error
Request issues an HMAC-signed request and unmarshals `envelope.data` into `out`. Pass nil out to discard the response body.
`body` is JSON-marshaled (compact, the Go default) before signing. The raw bytes that get signed are exactly the bytes that get sent over the wire — same invariant the backend enforces.
type ClientOptions ¶
type ClientOptions struct {
// KeyID — HMAC access key id, e.g. "AKIAFULK…". Required.
KeyID string
// Secret — HMAC secret. Required.
Secret string
// BaseURL — defaults to https://fulkruma.com (or $FULKRUMA_BASE_URL).
BaseURL string
// OnBehalfOf — merchant accountId forwarded as the
// `X-Fulkruma-On-Behalf-Of` header. Platform-admin scope only.
OnBehalfOf string
// Timeout — per-request HTTP timeout. Default 30s.
Timeout time.Duration
// HTTP — inject a pre-configured client (custom transport, retries).
// When nil the SDK constructs a fresh http.Client with Timeout.
HTTP *http.Client
// Now — clock source for signature timestamps; nil means time.Now.
// Useful for tests that re-derive the signature deterministically.
Now func() time.Time
}
ClientOptions controls FulkrumaClient construction. Empty fields fall back to the matching FULKRUMA_* env vars (KEY_ID, SECRET, BASE_URL, ON_BEHALF_OF) — keeping parity with the Node + Python SDKs.
type CustomerAddress ¶
type CustomerAddress struct {
ID string `json:"id"`
CustomerID string `json:"customerId"`
AccountID string `json:"accountId"`
Label string `json:"label"`
ContactName string `json:"contactName"`
ContactPhone string `json:"contactPhone"`
Email *string `json:"email"`
Address string `json:"address"`
PostalCode *string `json:"postalCode"`
AreaID *string `json:"areaId"`
Lat *float64 `json:"lat"`
Lng *float64 `json:"lng"`
BiteshipLocationID *string `json:"biteshipLocationId"`
IsDefault bool `json:"isDefault"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type DeletedEnvelope ¶
type DeletedEnvelope struct {
Deleted bool `json:"deleted"`
}
DeletedEnvelope wraps `{ deleted: bool }` responses.
type DeliveriesResource ¶
type DeliveriesResource struct {
// contains filtered or unexported fields
}
DeliveriesResource — /api/v1/deliveries.
func (*DeliveriesResource) Create ¶
func (r *DeliveriesResource) Create(ctx context.Context, in DeliveryCreateInput) (*Delivery, error)
Create — POST /api/v1/deliveries (idempotent).
type Delivery ¶
type Delivery struct {
ID string `json:"id"`
AccountID string `json:"accountId"`
ProductID string `json:"productId"`
CustomerID string `json:"customerId"`
CheckoutSessionID string `json:"checkoutSessionId"`
DownloadCount int64 `json:"downloadCount"`
MaxDownloads int64 `json:"maxDownloads"`
ExpiresAt string `json:"expiresAt"`
ExternalSource *string `json:"externalSource"`
ExternalRef *string `json:"externalRef"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type DeliveryCreateInput ¶
type DeliveryCreateInput struct {
ProductID string `json:"productId"`
CustomerID string `json:"customerId"`
CheckoutSessionID string `json:"checkoutSessionId"`
MaxDownloads *int64 `json:"maxDownloads,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
ExternalSource string `json:"externalSource,omitempty"`
ExternalRef string `json:"externalRef,omitempty"`
}
DeliveryCreateInput — POST /api/v1/deliveries body.
type EnvelopeMeta ¶
type EnvelopeMeta struct {
RequestID string `json:"requestId,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
Cursor string `json:"cursor,omitempty"`
HasMore bool `json:"hasMore,omitempty"`
}
EnvelopeMeta carries the pagination + tracing fields the backend returns alongside every response.
type Error ¶
Error is the single error type returned by every operation in this package. Mirrors the Node SDK's FulkrumaError: an HTTP status (0 for transport-level failures), an opaque code, a human message, and the optional upstream request id from the {meta:{requestId}} envelope.
type IntegrationsResource ¶
type IntegrationsResource struct {
// contains filtered or unexported fields
}
IntegrationsResource — /api/v1/integrations.
func (*IntegrationsResource) Status ¶
func (r *IntegrationsResource) Status(ctx context.Context) (*IntegrationsStatus, error)
Status — GET /api/v1/integrations/status.
type IntegrationsStatus ¶
type IntegrationsStatus struct {
Huudis map[string]any `json:"huudis,omitempty"`
Biteship map[string]any `json:"biteship,omitempty"`
Plugipay map[string]any `json:"plugipay,omitempty"`
Storlaunch map[string]any `json:"storlaunch,omitempty"`
}
IntegrationsStatus mirrors the per-provider status envelope.
type License ¶
type License struct {
ID string `json:"id"`
AccountID string `json:"accountId"`
ProductID string `json:"productId"`
CustomerID string `json:"customerId"`
Key string `json:"key"`
Status LicenseStatus `json:"status"`
Activations int64 `json:"activations"`
MaxActivations int64 `json:"maxActivations"`
ExpiresAt *string `json:"expiresAt"`
ExternalSource *string `json:"externalSource"`
ExternalRef *string `json:"externalRef"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type LicenseActivateInput ¶
LicenseActivateInput / LicenseDeactivateInput are public-unauthenticated.
type LicenseActivateResult ¶
type LicenseActivateResult struct {
License License `json:"license"`
Activation LicenseActivation `json:"activation"`
AlreadyActive bool `json:"alreadyActive"`
}
LicenseActivateResult mirrors the Node response.
type LicenseActivation ¶
type LicenseDeactivateResult ¶
type LicenseDeactivateResult struct {
Deactivated bool `json:"deactivated"`
AlreadyDeactivated bool `json:"alreadyDeactivated"`
Activations int64 `json:"activations"`
}
LicenseDeactivateResult mirrors the Node response.
type LicenseIssueInput ¶
type LicenseIssueInput struct {
ProductID string `json:"productId"`
CustomerID string `json:"customerId"`
MaxActivations *int64 `json:"maxActivations,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
ExternalSource string `json:"externalSource,omitempty"`
ExternalRef string `json:"externalRef,omitempty"`
}
LicenseIssueInput — POST /api/v1/licenses body.
type LicenseStatus ¶
type LicenseStatus string
LicenseStatus — "active" | "revoked".
const ( LicenseActive LicenseStatus = "active" LicenseRevoked LicenseStatus = "revoked" )
type LicenseValidateParams ¶
LicenseValidateParams — GET /licenses/validate query.
type LicenseValidateResult ¶
type LicenseValidateResult struct {
Valid bool `json:"valid"`
Key string `json:"key"`
Status *string `json:"status"`
ProductID *string `json:"productId"`
Activations *int64 `json:"activations"`
MaxActivations *int64 `json:"maxActivations"`
ExpiresAt *string `json:"expiresAt"`
}
LicenseValidateResult — payload returned by GET /licenses/validate.
type LicensesResource ¶
type LicensesResource struct {
// contains filtered or unexported fields
}
LicensesResource — /api/v1/licenses.
func (*LicensesResource) Activate ¶
func (r *LicensesResource) Activate(ctx context.Context, in LicenseActivateInput) (*LicenseActivateResult, error)
Activate — public unauthenticated. Pass arbitrary creds; the HMAC is still attached but the backend treats this route as unauthenticated.
func (*LicensesResource) Deactivate ¶
func (r *LicensesResource) Deactivate(ctx context.Context, in LicenseActivateInput) (*LicenseDeactivateResult, error)
Deactivate — public unauthenticated.
func (*LicensesResource) Issue ¶
func (r *LicensesResource) Issue(ctx context.Context, in LicenseIssueInput) (*License, error)
Issue — POST /api/v1/licenses (idempotent).
func (*LicensesResource) List ¶
func (r *LicensesResource) List(ctx context.Context) ([]License, error)
List — GET /api/v1/licenses.
func (*LicensesResource) Validate ¶
func (r *LicensesResource) Validate(ctx context.Context, p LicenseValidateParams) (*LicenseValidateResult, error)
Validate — public unauthenticated.
type PartnerUsageMerchant ¶
type PartnerUsageParams ¶
PartnerUsageParams — GET /admin/partner/usage query.
type PartnerUsagePeriod ¶
type PartnerUsageSummary ¶
type PartnerUsageSummary struct {
Partner string `json:"partner"`
Period PartnerUsagePeriod `json:"period"`
Totals PartnerUsageTotals `json:"totals"`
ByMerchant []PartnerUsageMerchant `json:"byMerchant"`
}
type PartnerUsageTotals ¶
type PartnerWorkspace ¶
type Product ¶
type Product struct {
ID string `json:"id"`
AccountID string `json:"accountId"`
Name string `json:"name"`
SKU *string `json:"sku"`
Description *string `json:"description"`
Type ProductType `json:"type"`
Weight *float64 `json:"weight"`
Length *float64 `json:"length"`
Width *float64 `json:"width"`
Height *float64 `json:"height"`
LicenseEnabled bool `json:"licenseEnabled"`
MaxActivations int64 `json:"maxActivations"`
ExternalRef *string `json:"externalRef"`
ExternalSource *string `json:"externalSource"`
Archived bool `json:"archived"`
Metadata map[string]any `json:"metadata"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Variants []ProductVariant `json:"variants,omitempty"`
}
Product matches the Node SDK type 1:1.
type ProductCreateInput ¶
type ProductCreateInput struct {
Name string `json:"name"`
SKU string `json:"sku,omitempty"`
Description string `json:"description,omitempty"`
Type ProductType `json:"type,omitempty"`
Weight *float64 `json:"weight,omitempty"`
Length *float64 `json:"length,omitempty"`
Width *float64 `json:"width,omitempty"`
Height *float64 `json:"height,omitempty"`
LicenseEnabled *bool `json:"licenseEnabled,omitempty"`
MaxActivations *int64 `json:"maxActivations,omitempty"`
ExternalRef string `json:"externalRef,omitempty"`
ExternalSource string `json:"externalSource,omitempty"`
}
ProductCreateInput is the request body for Products.Create. Optional fields are JSON-omitempty so zero values don't override backend defaults.
type ProductEnvelope ¶
type ProductEnvelope struct {
Product Product `json:"product"`
}
ProductEnvelope wraps `{ product: Product }` responses.
type ProductListEnvelope ¶
type ProductListEnvelope struct {
Products []Product `json:"products"`
}
ProductListEnvelope wraps `{ products: [] }` responses.
type ProductListParams ¶
type ProductListParams struct {
Archived *bool
}
ProductListParams filters the list endpoint.
type ProductType ¶
type ProductType string
ProductType — "physical" | "digital" | "license".
const ( ProductTypePhysical ProductType = "physical" ProductTypeDigital ProductType = "digital" ProductTypeLicense ProductType = "license" )
type ProductUpdateInput ¶
type ProductUpdateInput struct {
Name *string `json:"name,omitempty"`
SKU *string `json:"sku,omitempty"`
Description *string `json:"description,omitempty"`
Type *ProductType `json:"type,omitempty"`
Weight *float64 `json:"weight,omitempty"`
Length *float64 `json:"length,omitempty"`
Width *float64 `json:"width,omitempty"`
Height *float64 `json:"height,omitempty"`
LicenseEnabled *bool `json:"licenseEnabled,omitempty"`
MaxActivations *int64 `json:"maxActivations,omitempty"`
ExternalRef *string `json:"externalRef,omitempty"`
ExternalSource *string `json:"externalSource,omitempty"`
}
ProductUpdateInput patches a product — every field is optional.
type ProductVariant ¶
type ProductVariant struct {
ID string `json:"id"`
ProductID string `json:"productId"`
SKU *string `json:"sku"`
Name string `json:"name"`
PriceCents int64 `json:"priceCents"`
CostCents *int64 `json:"costCents"`
LowStockThreshold *int64 `json:"lowStockThreshold"`
Weight *float64 `json:"weight"`
IsDefault bool `json:"isDefault"`
Archived bool `json:"archived"`
ExternalRef *string `json:"externalRef"`
ExternalSource *string `json:"externalSource"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
ProductVariant matches the Node SDK type 1:1.
type ProductsResource ¶
type ProductsResource struct {
// contains filtered or unexported fields
}
ProductsResource groups every /api/v1/products call.
func (*ProductsResource) AddVariant ¶
func (r *ProductsResource) AddVariant(ctx context.Context, productID string, in VariantCreateInput) (*ProductVariant, error)
AddVariant — POST /api/v1/products/:id/variants.
func (*ProductsResource) ArchiveVariant ¶
func (r *ProductsResource) ArchiveVariant(ctx context.Context, productID, variantID string) (bool, error)
ArchiveVariant — DELETE /api/v1/products/:productId/variants/:variantId.
func (*ProductsResource) Create ¶
func (r *ProductsResource) Create(ctx context.Context, in ProductCreateInput) (*Product, error)
Create — POST /api/v1/products (idempotent via auto-generated key).
func (*ProductsResource) List ¶
func (r *ProductsResource) List(ctx context.Context, p ProductListParams) ([]Product, error)
List — GET /api/v1/products.
func (*ProductsResource) Update ¶
func (r *ProductsResource) Update(ctx context.Context, id string, patch ProductUpdateInput) (*Product, error)
Update — PATCH /api/v1/products/:id.
func (*ProductsResource) UpdateVariant ¶
func (r *ProductsResource) UpdateVariant(ctx context.Context, productID, variantID string, patch VariantUpdateInput) (*ProductVariant, error)
UpdateVariant — PATCH /api/v1/products/:productId/variants/:variantId.
type ProvisionWorkspaceInput ¶
type ProvisionWorkspaceInput struct {
AccountID string `json:"accountId"`
Partner string `json:"partner"`
DiscountRate float64 `json:"discountRate"`
BrandName string `json:"brandName,omitempty"`
BusinessEmail string `json:"businessEmail,omitempty"`
}
ProvisionWorkspaceInput — POST /admin/workspaces body.
type RequestOptions ¶
type RequestOptions struct {
IdempotencyKey string
OnBehalfOf string // per-call override; "" falls back to default
}
RequestOptions tunes a single low-level Request call. Most callers use the typed resource methods instead.
type RevokedEnvelope ¶
type RevokedEnvelope struct {
Revoked bool `json:"revoked"`
}
RevokedEnvelope wraps `{ revoked: bool }`.
type Shipment ¶
type Shipment struct {
ID string `json:"id"`
AccountID string `json:"accountId"`
ProductID *string `json:"productId"`
CheckoutSessionID *string `json:"checkoutSessionId"`
CustomerID *string `json:"customerId"`
CustomerEmail *string `json:"customerEmail"`
BiteshipOrderID string `json:"biteshipOrderId"`
BiteshipTrackingID *string `json:"biteshipTrackingId"`
WaybillID *string `json:"waybillId"`
CourierCode string `json:"courierCode"`
CourierServiceCode string `json:"courierServiceCode"`
CourierType string `json:"courierType"`
Status ShipmentStatus `json:"status"`
TrackingURL *string `json:"trackingUrl"`
LabelURL *string `json:"labelUrl"`
Price float64 `json:"price"`
Insurance float64 `json:"insurance"`
Insured bool `json:"insured"`
OriginSnapshot map[string]any `json:"originSnapshot"`
DestinationSnapshot map[string]any `json:"destinationSnapshot"`
Items []map[string]any `json:"items"`
CancelReason *string `json:"cancelReason"`
ExternalSource *string `json:"externalSource"`
ExternalRef *string `json:"externalRef"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type ShipmentCreateInput ¶
type ShipmentCreateInput struct {
ProductID string `json:"productId,omitempty"`
CheckoutSessionID string `json:"checkoutSessionId,omitempty"`
CustomerID string `json:"customerId,omitempty"`
CustomerEmail string `json:"customerEmail,omitempty"`
CourierCode string `json:"courierCode"`
CourierServiceCode string `json:"courierServiceCode"`
CourierType string `json:"courierType"`
Price float64 `json:"price"`
Insurance *float64 `json:"insurance,omitempty"`
Insured *bool `json:"insured,omitempty"`
Origin map[string]any `json:"origin"`
Destination map[string]any `json:"destination"`
Items []map[string]any `json:"items"`
ExternalSource string `json:"externalSource,omitempty"`
ExternalRef string `json:"externalRef,omitempty"`
}
ShipmentCreateInput is intentionally loosely typed to match the Node SDK — origin/destination/items are arbitrary JSON shapes the backend validates.
type ShipmentStatus ¶
type ShipmentStatus string
ShipmentStatus — enumerated.
const ( ShipmentPending ShipmentStatus = "pending" ShipmentConfirmed ShipmentStatus = "confirmed" ShipmentAllocated ShipmentStatus = "allocated" ShipmentPickingUp ShipmentStatus = "picking_up" ShipmentPickedUp ShipmentStatus = "picked_up" ShipmentDroppingOff ShipmentStatus = "dropping_off" ShipmentInTransit ShipmentStatus = "in_transit" ShipmentDelivered ShipmentStatus = "delivered" ShipmentCancelled ShipmentStatus = "cancelled" ShipmentReturned ShipmentStatus = "returned" ShipmentFailed ShipmentStatus = "failed" )
type ShipmentsResource ¶
type ShipmentsResource struct {
// contains filtered or unexported fields
}
ShipmentsResource — /api/v1/shipments.
func (*ShipmentsResource) Create ¶
func (r *ShipmentsResource) Create(ctx context.Context, in ShipmentCreateInput) (*Shipment, error)
Create — POST /api/v1/shipments (idempotent).
type ShippingRatesInput ¶
type ShippingRatesInput struct {
Destination map[string]any `json:"destination"`
Items []map[string]any `json:"items"`
Insurance *bool `json:"insurance,omitempty"`
}
ShippingRatesInput — POST /api/v1/shipping/rates body.
type ShippingResource ¶
type ShippingResource struct {
// contains filtered or unexported fields
}
ShippingResource — /api/v1/shipping/*.
func (*ShippingResource) Couriers ¶
Couriers — GET /api/v1/shipping/couriers (untyped — passthrough to backend).
func (*ShippingResource) Rates ¶
func (r *ShippingResource) Rates(ctx context.Context, in ShippingRatesInput) (map[string]any, error)
Rates — POST /api/v1/shipping/rates.
type StatsOverview ¶
type StatsOverview struct {
Counters map[string]int64 `json:"counters"`
Recent map[string]any `json:"recent"`
}
StatsOverview mirrors the overview envelope.
type StatsResource ¶
type StatsResource struct {
// contains filtered or unexported fields
}
StatsResource — /api/v1/stats.
func (*StatsResource) Overview ¶
func (r *StatsResource) Overview(ctx context.Context) (*StatsOverview, error)
Overview — GET /api/v1/stats/overview.
type StockAdjustInput ¶
type StockAdjustInput struct {
VariantID string `json:"variantId"`
WarehouseID string `json:"warehouseId"`
Delta int64 `json:"delta"`
Reason StockMovementReason `json:"reason"`
Note string `json:"note,omitempty"`
}
StockAdjustInput — POST /api/v1/stock/adjust body.
type StockAdjustResult ¶
type StockAdjustResult struct {
Stock VariantStock `json:"stock"`
Movement StockMovement `json:"movement"`
}
StockAdjustResult mirrors `{ stock, movement }`.
type StockMovement ¶
type StockMovement struct {
ID string `json:"id"`
VariantID string `json:"variantId"`
WarehouseID string `json:"warehouseId"`
Delta int64 `json:"delta"`
Reason StockMovementReason `json:"reason"`
ReferenceID *string `json:"referenceId"`
Note *string `json:"note"`
CreatedAt string `json:"createdAt"`
CreatedBy *string `json:"createdBy"`
}
type StockMovementReason ¶
type StockMovementReason string
StockMovementReason — enumerated values match Node SDK.
const ( StockMovementManualAdjust StockMovementReason = "manual_adjust" StockMovementCheckoutReserve StockMovementReason = "checkout_reserve" StockMovementCheckoutCommit StockMovementReason = "checkout_commit" StockMovementCheckoutRelease StockMovementReason = "checkout_release" StockMovementRefundRestock StockMovementReason = "refund_restock" StockMovementTransferIn StockMovementReason = "transfer_in" StockMovementTransferOut StockMovementReason = "transfer_out" StockMovementDamaged StockMovementReason = "damaged" StockMovementReturnedToSupplier StockMovementReason = "returned_to_supplier" StockMovementInitialStock StockMovementReason = "initial_stock" StockMovementImport StockMovementReason = "import" )
type StockReservation ¶
type StockReservation struct {
ID string `json:"id"`
VariantID string `json:"variantId"`
WarehouseID string `json:"warehouseId"`
Quantity int64 `json:"quantity"`
CheckoutSessionID string `json:"checkoutSessionId"`
ExpiresAt string `json:"expiresAt"`
ConsumedAt *string `json:"consumedAt"`
ReleasedAt *string `json:"releasedAt"`
CreatedAt string `json:"createdAt"`
}
type StockResource ¶
type StockResource struct {
// contains filtered or unexported fields
}
StockResource — /api/v1/stock.
func (*StockResource) Adjust ¶
func (r *StockResource) Adjust(ctx context.Context, in StockAdjustInput) (*StockAdjustResult, error)
Adjust — POST /api/v1/stock/adjust (idempotent).
func (*StockResource) Levels ¶
func (r *StockResource) Levels(ctx context.Context, variantID string) ([]VariantStock, error)
Levels — GET /api/v1/stock/levels.
func (*StockResource) Movements ¶
func (r *StockResource) Movements(ctx context.Context, variantID string) ([]StockMovement, error)
Movements — GET /api/v1/stock/movements.
func (*StockResource) Reservations ¶
func (r *StockResource) Reservations(ctx context.Context) ([]StockReservation, error)
Reservations — GET /api/v1/stock/reservations.
type VariantCreateInput ¶
type VariantCreateInput struct {
Name string `json:"name"`
SKU string `json:"sku,omitempty"`
PriceCents *int64 `json:"priceCents,omitempty"`
CostCents *int64 `json:"costCents,omitempty"`
LowStockThreshold *int64 `json:"lowStockThreshold,omitempty"`
Weight *float64 `json:"weight,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
ExternalRef string `json:"externalRef,omitempty"`
ExternalSource string `json:"externalSource,omitempty"`
}
VariantCreateInput is the request body for Products.AddVariant.
type VariantEnvelope ¶
type VariantEnvelope struct {
Variant ProductVariant `json:"variant"`
}
VariantEnvelope wraps `{ variant: ProductVariant }` responses.
type VariantStock ¶
type VariantStockWarehouseRef ¶
VariantStockWarehouseRef is the truncated warehouse hint the backend inlines on level responses.
type VariantUpdateInput ¶
type VariantUpdateInput struct {
Name *string `json:"name,omitempty"`
SKU *string `json:"sku,omitempty"`
PriceCents *int64 `json:"priceCents,omitempty"`
CostCents *int64 `json:"costCents,omitempty"`
LowStockThreshold *int64 `json:"lowStockThreshold,omitempty"`
Weight *float64 `json:"weight,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
ExternalRef *string `json:"externalRef,omitempty"`
ExternalSource *string `json:"externalSource,omitempty"`
}
VariantUpdateInput is the PATCH-only counterpart.
type VerifyWebhookOptions ¶
type VerifyWebhookOptions struct {
// ToleranceSec — max drift in seconds between the signature timestamp
// and the current clock. Default 300 (5 min). Zero or negative means
// "use the default".
ToleranceSec int64
// Now — clock for the freshness check. Nil means time.Now. Useful in
// tests.
Now func() time.Time
}
VerifyWebhookOptions tunes VerifyWebhook. A nil pointer uses defaults.
type Warehouse ¶
type Warehouse struct {
ID string `json:"id"`
AccountID string `json:"accountId"`
Name string `json:"name"`
Address *string `json:"address"`
City *string `json:"city"`
Postal *string `json:"postal"`
Phone *string `json:"phone"`
IsDefault bool `json:"isDefault"`
Archived bool `json:"archived"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type WarehouseCreateInput ¶
type WarehouseCreateInput struct {
Name string `json:"name"`
Address string `json:"address,omitempty"`
City string `json:"city,omitempty"`
Postal string `json:"postal,omitempty"`
Lat *float64 `json:"lat,omitempty"`
Lng *float64 `json:"lng,omitempty"`
Phone string `json:"phone,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
}
WarehouseCreateInput — POST /api/v1/warehouses body.
type WarehouseUpdateInput ¶
type WarehouseUpdateInput struct {
Name *string `json:"name,omitempty"`
Address *string `json:"address,omitempty"`
City *string `json:"city,omitempty"`
Postal *string `json:"postal,omitempty"`
Lat *float64 `json:"lat,omitempty"`
Lng *float64 `json:"lng,omitempty"`
Phone *string `json:"phone,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
}
WarehouseUpdateInput — PATCH-only counterpart.
type WarehousesResource ¶
type WarehousesResource struct {
// contains filtered or unexported fields
}
WarehousesResource — /api/v1/warehouses.
func (*WarehousesResource) Create ¶
func (r *WarehousesResource) Create(ctx context.Context, in WarehouseCreateInput) (*Warehouse, error)
Create — POST /api/v1/warehouses.
func (*WarehousesResource) List ¶
func (r *WarehousesResource) List(ctx context.Context) ([]Warehouse, error)
List — GET /api/v1/warehouses.
func (*WarehousesResource) Update ¶
func (r *WarehousesResource) Update(ctx context.Context, id string, patch WarehouseUpdateInput) (*Warehouse, error)
Update — PATCH /api/v1/warehouses/:id.
type WebhookEndpointCreateInput ¶
type WebhookEndpointCreateInput struct {
URL string `json:"url"`
Events []string `json:"events,omitempty"`
Description string `json:"description,omitempty"`
}
WebhookEndpointCreateInput — POST /webhooks/endpoints body.
type WebhookEndpointUpdateInput ¶
type WebhookEndpointUpdateInput struct {
URL *string `json:"url,omitempty"`
Events *[]string `json:"events,omitempty"`
Description *string `json:"description,omitempty"`
Active *bool `json:"active,omitempty"`
}
WebhookEndpointUpdateInput — PATCH body. Fields are pointers to distinguish "leave alone" from "set to zero".
type WebhookEventEnvelope ¶
type WebhookEventEnvelope struct {
ID string `json:"id"`
Type string `json:"type"`
OccurredAt string `json:"occurredAt"`
AccountID *string `json:"accountId"`
Data json.RawMessage `json:"data"`
Metadata map[string]any `json:"metadata"`
}
WebhookEventEnvelope is the parsed shape returned by VerifyWebhook. Data stays as RawMessage so callers can switch on Type before unmarshaling.
func VerifyWebhook ¶
func VerifyWebhook(rawBody []byte, signatureHeader, secret string, opts *VerifyWebhookOptions) (*WebhookEventEnvelope, error)
VerifyWebhook verifies and parses an inbound Fulkruma webhook.
Fulkruma signs every webhook delivery with::
Fulkruma-Signature: t=<unix>,v1=<hex>
where `<hex> = HMAC-SHA256(secret, fmt.Sprintf("%s.%s", t, rawBody))`. The raw body bytes are what got signed — re-serialising parsed JSON will drift whitespace and the signature will never match.
Returns the parsed envelope on success. Returns *Error on any failure (missing header, drift, bad signature, malformed JSON).
net/http example:
func fulkrumaWebhook(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil { http.Error(w, "bad body", 400); return }
sig := r.Header.Get("Fulkruma-Signature")
event, err := fulkruma.VerifyWebhook(body, sig, os.Getenv("FULKRUMA_WEBHOOK_SECRET"), nil)
if err != nil { http.Error(w, err.Error(), 400); return }
// switch event.Type { … }; reply 204.
}
type WebhookEventsListParams ¶
WebhookEventsListParams — GET /webhooks/events query.
type WebhookEventsListResult ¶
type WebhookEventsListResult struct {
Events []map[string]any `json:"events"`
NextCursor string `json:"nextCursor,omitempty"`
}
WebhookEventsListResult mirrors the cursor-paginated envelope.
type WebhooksResource ¶
type WebhooksResource struct {
// contains filtered or unexported fields
}
WebhooksResource — /api/v1/webhooks/*. (For signature verification of inbound deliveries, see VerifyWebhook.)
func (*WebhooksResource) CreateEndpoint ¶
func (r *WebhooksResource) CreateEndpoint(ctx context.Context, in WebhookEndpointCreateInput) (map[string]any, error)
CreateEndpoint — POST /api/v1/webhooks/endpoints (idempotent).
func (*WebhooksResource) DeleteEndpoint ¶
DeleteEndpoint — DELETE /api/v1/webhooks/endpoints/:id.
func (*WebhooksResource) ListEndpoints ¶
ListEndpoints — GET /api/v1/webhooks/endpoints.
func (*WebhooksResource) ListEvents ¶
func (r *WebhooksResource) ListEvents(ctx context.Context, p WebhookEventsListParams) (*WebhookEventsListResult, error)
ListEvents — GET /api/v1/webhooks/events.
func (*WebhooksResource) UpdateEndpoint ¶
func (r *WebhooksResource) UpdateEndpoint(ctx context.Context, id string, patch WebhookEndpointUpdateInput) (map[string]any, error)
UpdateEndpoint — PATCH /api/v1/webhooks/endpoints/:id.