Documentation
¶
Overview ¶
Package vtex is a client for the public VTEX storefront APIs: catalog search, checkout orderForm, delivery simulation, VTEX ID auth, and order history.
Nothing here is store-specific. Every store-dependent value comes from the store.Store descriptor the client is constructed with.
Index ¶
- Constants
- Variables
- func GenerateClearSaleSession(doer store.HTTPDoer, endpoint string) (string, error)
- type Client
- func (c *Client) AddToCart(orderFormID, skuID, seller string, quantity int) (*OrderForm, error)
- func (c *Client) AddToWishlist(shopperID, listName string, item WishlistItem) error
- func (c *Client) AuthStart() (*store.Capabilities, error)
- func (c *Client) AuthToken() string
- func (c *Client) AuthenticatedUser() (string, error)
- func (c *Client) AwaitOrderSettlement(orderGroup string) (*OrderDetail, error)
- func (c *Client) ClassicLogin(email, password string) (string, error)
- func (c *Client) GatewayCallback(orderGroup string) error
- func (c *Client) Get(path string) ([]byte, error)
- func (c *Client) GetDeliveryWindows(orderFormID string) ([]DeliveryWindow, error)
- func (c *Client) GetOrder(orderID string) (*OrderDetail, error)
- func (c *Client) GetOrderForm(orderFormID string) (*OrderForm, error)
- func (c *Client) GetSavedCards(orderFormID string) ([]SavedCard, error)
- func (c *Client) GetSession() (*Session, error)
- func (c *Client) GetSubscription(id string) (*Subscription, error)
- func (c *Client) HTTPClient() *http.Client
- func (c *Client) ListOrders() ([]Order, error)
- func (c *Client) ListSubscriptions() ([]Subscription, error)
- func (c *Client) Login(ctx context.Context, email, password string) (string, error)
- func (c *Client) NewOrderForm() (*OrderForm, error)
- func (c *Client) PatchJSON(path string, payload any) ([]byte, error)
- func (c *Client) PayWithSavedCard(tx *TransactionResult, card SavedCard, cvv string, orderValue money.Centavos) error
- func (c *Client) PlaceOrder(orderFormID string, orderValue money.Centavos) (*TransactionResult, error)
- func (c *Client) PostForm(path string, values url.Values) ([]byte, error)
- func (c *Client) PostJSON(path string, payload any) ([]byte, error)
- func (c *Client) PostJSONAbsolute(absoluteURL string, payload any) ([]byte, error)
- func (c *Client) RefreshToken() (string, error)
- func (c *Client) RemoveAllItems(orderFormID string) error
- func (c *Client) RemoveFromWishlist(shopperID, listName string, id int) (bool, error)
- func (c *Client) ResolvePaymentSystem(of *OrderForm, name string) (int, error)
- func (c *Client) Search(query string, limit int) ([]SearchResult, error)
- func (c *Client) SendAccessCode(email string) error
- func (c *Client) SetAddress(orderFormID string, numItems int) error
- func (c *Client) SetAuthToken(token string)
- func (c *Client) SetPayment(orderFormID string, paymentSystemID int, value money.Centavos) error
- func (c *Client) SetPaymentWithSavedCard(orderFormID string, card SavedCard, value money.Centavos) error
- func (c *Client) SetShippingWindow(orderFormID string, window DeliveryWindow, numItems int) error
- func (c *Client) SetSubscriptionStatus(id, status string) (*Subscription, error)
- func (c *Client) Simulate(items []SimulationItemRequest, cep string) (*Simulation, error)
- func (c *Client) SkipSubscription(id string, skip bool) (*Subscription, error)
- func (c *Client) Store() store.Store
- func (c *Client) UpdateItemQuantity(orderFormID string, index, quantity int) (*OrderForm, error)
- func (c *Client) UsableCart(persistedID string) (*OrderForm, bool, error)
- func (c *Client) ValidateAccessCode(code, emailOverride string) (string, string, error)
- func (c *Client) Wishlists(shopperID string) ([]Wishlist, error)
- type DeliveryWindow
- type Frequency
- type Order
- type OrderDetail
- type OrderForm
- type OrderFormItem
- type OrderItem
- type OrderPayment
- type PaymentSystem
- type PendingAuth
- type SavedCard
- type SearchResult
- type Session
- type Simulation
- type SimulationItem
- type SimulationItemRequest
- type SimulationLogisticsInfo
- type SimulationSLA
- type Subscription
- type SubscriptionItem
- type SubscriptionPlan
- type SubscriptionSettings
- type Totalizer
- type TransactionResult
- type Wishlist
- type WishlistItem
Constants ¶
const ( SubscriptionActive = "ACTIVE" SubscriptionPaused = "PAUSED" SubscriptionCanceled = "CANCELED" SubscriptionExpired = "EXPIRED" SubscriptionMissing = "MISSING" )
Subscription statuses reported by the RNS API. CANCELED is terminal, which is why this package exposes no way to reach it.
const DefaultWishlistName = "Wishlist"
DefaultWishlistName is the list vtex.wish-list writes to when the storefront's heart icon is used.
Variables ¶
var ErrAccessKeyRequired = errors.New("store requires an emailed access code")
ErrAccessKeyRequired reports that the only login method the store offers is an emailed access code, which cannot complete in a single call. The caller must run SendAccessCode, collect the code, then ValidateAccessCode.
Functions ¶
func GenerateClearSaleSession ¶
GenerateClearSaleSession registers an anti-fraud device fingerprint and returns the session ID to send as deviceFingerprint on a card payment.
Nothing here is store-specific — the app key and SDK identifiers are common to the VTEX/ClearSale integration — so it lives in the library and is reached only when a store sets the ClearSaleFingerprint quirk.
doer and endpoint are injected: the original implementation called the package-level http.Get, which bypassed the client's transport and had no timeout, so a hung ClearSale host stalled checkout indefinitely.
Types ¶
type Client ¶
type Client struct {
// GatewayURL overrides the payment gateway host. Tests set it; empty
// means the production vtexpayments host derived from the account.
GatewayURL string
// ClearSaleURL overrides the ClearSale fingerprint host for tests.
ClearSaleURL string
// SettlementInterval overrides the delay between order settlement
// polls. Tests shorten it; zero means the default.
SettlementInterval time.Duration
// SubscriptionsURL overrides the Subscriptions (RNS) host. Tests set it;
// empty means the account host from store.AccountBaseURL.
SubscriptionsURL string
// contains filtered or unexported fields
}
func (*Client) AddToCart ¶
AddToCart adds a SKU. The seller comes from the caller — normally straight off a SearchResult — because it is not a store-wide constant.
func (*Client) AddToWishlist ¶ added in v0.4.0
func (c *Client) AddToWishlist(shopperID, listName string, item WishlistItem) error
AddToWishlist saves a product to the shopper's wishlist. productID and sku differ for products with variants and the API wants both.
func (*Client) AuthStart ¶
func (c *Client) AuthStart() (*store.Capabilities, error)
AuthStart probes what login methods this store supports.
func (*Client) AuthenticatedUser ¶
AuthenticatedUser returns the logged-in email, or an error when the stored token has expired.
func (*Client) AwaitOrderSettlement ¶ added in v0.4.3
func (c *Client) AwaitOrderSettlement(orderGroup string) (*OrderDetail, error)
AwaitOrderSettlement re-reads an order until the gateway has settled a payment on it, the store has cancelled it, or the poll budget runs out.
Running out is an answer, not an error: the caller gets the last state the store reported and must say so rather than claim a placed order. Only an order that could not be read at all is an error, because then there is nothing true to report.
func (*Client) ClassicLogin ¶
ClassicLogin authenticates with email and password against stock VTEX ID.
func (*Client) GatewayCallback ¶
GatewayCallback finalizes a card payment. The gateway answers 428 while the transaction is still settling, so this retries with a linear backoff.
func (*Client) GetDeliveryWindows ¶
func (c *Client) GetDeliveryWindows(orderFormID string) ([]DeliveryWindow, error)
GetDeliveryWindows lists the windows available for the cart's address. Requires an orderForm with a shipping address, so it needs authentication; use Simulate for an unauthenticated check.
Windows are deduplicated across items and reindexed from zero, because `--window N` indexes into the returned slice.
func (*Client) GetOrder ¶
func (c *Client) GetOrder(orderID string) (*OrderDetail, error)
GetOrder reads one order.
Checkout reports the order *group*, which is the id a caller actually holds, while OMS keys orders as "<group>-<seq>". The id is tried exactly as given first, so a full order id behaves as it always has; the fallback only makes the id the CLI printed usable. A group id answers either 404 or a body with no order in it, and neither is an order.
func (*Client) GetSavedCards ¶
func (*Client) GetSession ¶
GetSession reads the auth cookie, cart pointer, and logged-in email from the VTEX sessions API.
The auth cookie key is account-scoped (VtexIdclientAutCookie_frescatto), so the response cannot be unmarshalled through a fixed struct tag the way the pre-extraction implementations did. It is decoded into a map and looked up by the descriptor's cookie name.
func (*Client) GetSubscription ¶ added in v0.5.0
func (c *Client) GetSubscription(id string) (*Subscription, error)
func (*Client) HTTPClient ¶
func (*Client) ListOrders ¶
func (*Client) ListSubscriptions ¶ added in v0.5.0
func (c *Client) ListSubscriptions() ([]Subscription, error)
ListSubscriptions returns the shopper's subscriptions.
The endpoint takes a customerEmail filter, but a shopper token already scopes the result to its own customer — verified against a live account — so passing one would only cost an extra round trip to learn our own email.
func (*Client) Login ¶
Login authenticates with whichever strategy the store supports, preferring a registered OAuth driver, then classic email+password, then access key.
The strategy is discovered rather than declared: a store descriptor does not say how to log in, the storefront does.
func (*Client) NewOrderForm ¶
NewOrderForm mints a genuinely new cart.
It must use its own cookie jar: VTEX pins a client to its current cart via a checkout cookie, so calling GET /orderForm on a client that has already touched a cart hands back that same cart. Without a clean jar this silently returns the cart you were trying to escape.
func (*Client) PayWithSavedCard ¶
func (c *Client) PayWithSavedCard(tx *TransactionResult, card SavedCard, cvv string, orderValue money.Centavos) error
PayWithSavedCard submits a card payment to the VTEX payment gateway.
ClearSale fingerprinting is applied only for stores carrying the ClearSaleFingerprint quirk. Zona Sul's gateway rejects card payments without it (Cielo code 59); Frescatto shows no sign of needing it.
func (*Client) PlaceOrder ¶
func (c *Client) PlaceOrder(orderFormID string, orderValue money.Centavos) (*TransactionResult, error)
PlaceOrder converts the cart into a transaction. This is the point of no return for non-card payments.
func (*Client) PostForm ¶
PostForm submits form-encoded values. VTEX ID's validate endpoints reject JSON bodies, so auth uses this rather than PostJSON.
func (*Client) PostJSONAbsolute ¶
PostJSONAbsolute posts to a full URL rather than a storefront path. The payment gateway lives on a different host, so it cannot use PostJSON.
func (*Client) RefreshToken ¶
RefreshToken asks the sessions API for a fresher JWT. It returns an empty string when the session carries no token, which means the caller must re-authenticate rather than treat it as an error.
func (*Client) RemoveAllItems ¶
func (*Client) RemoveFromWishlist ¶ added in v0.4.0
RemoveFromWishlist deletes an item by its wishlist ID, which is not the SKU. Callers resolve a SKU to an ID by reading the list first.
func (*Client) ResolvePaymentSystem ¶
ResolvePaymentSystem maps a human name such as "pix" to the store's own payment system ID, discovered from the order form. IDs are not portable between stores, so this replaces the hardcoded map the CLIs used to carry.
func (*Client) Search ¶
func (c *Client) Search(query string, limit int) ([]SearchResult, error)
Search queries the store catalog using the descriptor's configured mode.
SearchAuto tries Intelligent Search REST first and falls back to the catalog REST API. Neither needs a persisted GraphQL hash, which is what made the previous implementation brittle: VTEX rotates that hash on every search-graphql release and a stale one returns no results.
func (*Client) SendAccessCode ¶
SendAccessCode emails a one-time login code and records the pending authentication token, which the subsequent validate call must reuse.
func (*Client) SetAddress ¶
SetAddress applies the account's saved delivery address to the cart.
func (*Client) SetAuthToken ¶
func (*Client) SetPayment ¶
func (*Client) SetPaymentWithSavedCard ¶
func (*Client) SetShippingWindow ¶
func (c *Client) SetShippingWindow(orderFormID string, window DeliveryWindow, numItems int) error
SetShippingWindow selects a delivery window for every item in the cart.
func (*Client) SetSubscriptionStatus ¶ added in v0.5.0
func (c *Client) SetSubscriptionStatus(id, status string) (*Subscription, error)
SetSubscriptionStatus moves a subscription between ACTIVE and PAUSED.
CANCELED is deliberately refused. RNS has no transition out of it, so a mistyped ID would destroy a subscription with no way back from this CLI.
func (*Client) Simulate ¶
func (c *Client) Simulate(items []SimulationItemRequest, cep string) (*Simulation, error)
Simulate prices a basket against a postal code without authentication. This is how delivery windows and payment methods can be inspected before anyone logs in.
func (*Client) SkipSubscription ¶ added in v0.5.0
func (c *Client) SkipSubscription(id string, skip bool) (*Subscription, error)
SkipSubscription skips the next cycle, or restores it when skip is false.
func (*Client) UpdateItemQuantity ¶
UpdateItemQuantity sets an absolute quantity, not a delta. Setting 0 removes the item.
func (*Client) UsableCart ¶
UsableCart returns a cart that can actually complete a checkout.
VTEX snapshots account data into an order form at creation time and never refreshes it — refreshOutdatedData does not help. A cart minted before the account had a profile or address is therefore permanently unusable, and because the CLI persists a cart id across invocations, a user who tried the CLI before completing their profile would be stuck forever with no way out but deleting the config by hand.
When the persisted cart cannot check out, this mints a fresh one and carries the items across, so nothing the user added is lost.
func (*Client) ValidateAccessCode ¶
ValidateAccessCode exchanges an emailed code for a JWT. It returns the token and the email it authenticated, then clears the pending record.
type DeliveryWindow ¶
type DeliveryWindow struct {
Index int `json:"index"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
Price money.Centavos `json:"price"`
LisPrice money.Centavos `json:"lisPrice"`
Tax money.Centavos `json:"tax"`
// RawStart and RawEnd preserve the exact strings VTEX sent. The
// shipping-window request must echo them back byte for byte; a
// re-formatted timestamp is rejected.
RawStart string `json:"-"`
RawEnd string `json:"-"`
}
type Frequency ¶ added in v0.5.0
Frequency is how often a subscription reorders: interval 2 with periodicity WEEKLY means every two weeks.
type OrderDetail ¶
type OrderDetail struct {
OrderID string `json:"orderId"`
Status string `json:"status"`
StatusDescription string `json:"statusDescription,omitempty"`
CreationDate string `json:"creationDate,omitempty"`
AuthorizedDate string `json:"authorizedDate,omitempty"`
Value money.Centavos `json:"value"`
Authorized bool `json:"authorized"`
TID string `json:"tid,omitempty"`
Payments []OrderPayment `json:"payments,omitempty"`
Items []OrderItem `json:"items"`
}
OrderDetail is one order as the store reports it after the fact.
Authorized and TID are derived at parse time because they answer the only question worth asking once an order exists: did money actually move. On 2026-08-18 a Frescatto order printed as placed while every payment on it carried a null tid and an empty connector response; the gateway cancelled it five minutes later.
func (*OrderDetail) Canceled ¶ added in v0.4.3
func (o *OrderDetail) Canceled() bool
Canceled reports whether the store has cancelled this order or started to. Every VTEX cancellation status carries the word.
type OrderForm ¶
type OrderForm struct {
OrderFormID string `json:"orderFormId"`
Items []OrderFormItem `json:"items"`
Totalizers []Totalizer `json:"totalizers"`
PaymentSystems []PaymentSystem `json:"-"`
Value money.Centavos `json:"value"`
LoggedIn bool `json:"loggedIn"`
// AddressCount is how many delivery addresses this cart can see. VTEX
// snapshots account data into an order form when it is created, so a
// cart minted before the account had an address reports zero here
// forever — it can never complete a checkout.
AddressCount int `json:"addressCount"`
}
func (*OrderForm) Checkoutable ¶
Checkoutable reports whether this cart can reach a completed order. A cart with no visible address cannot, regardless of what the account has.
func (*OrderForm) ItemsTotal ¶
ItemsTotal returns the Items totalizer, which excludes shipping. Checkout minimums are assessed against this, not the order total.
type OrderFormItem ¶
type OrderFormItem struct {
ID string `json:"id"`
ProductID string `json:"productId"`
Name string `json:"name"`
Quantity int `json:"quantity"`
Price money.Centavos `json:"price"`
SellingPrice money.Centavos `json:"sellingPrice"`
Seller string `json:"seller"`
Unit string `json:"measurementUnit"`
UnitMult float64 `json:"unitMultiplier"`
}
type OrderPayment ¶ added in v0.4.3
type OrderPayment struct {
ID string `json:"id"`
PaymentSystemName string `json:"paymentSystemName"`
Group string `json:"group"`
Value money.Centavos `json:"value"`
TID string `json:"tid"`
ConnectorResponses map[string]any `json:"connectorResponses,omitempty"`
}
OrderPayment is one payment on a placed order, as the store reports it afterwards. Card and account identifiers are deliberately not modeled: nothing this CLI does needs them, and what is not parsed cannot leak.
type PaymentSystem ¶
type PaymentSystem struct {
ID int `json:"id"`
Name string `json:"name"`
GroupName string `json:"groupName"`
}
PaymentSystem is one payment method the store accepts. Discovered from the orderForm rather than hardcoded, because the set differs per store.
type PendingAuth ¶
type PendingAuth struct {
Email string `json:"email"`
AuthenticationToken string `json:"authenticationToken"`
}
PendingAuth records an in-flight access-code login. VTEX rejects a validate call whose authenticationToken came from a different start call, so the token has to survive between the two CLI invocations.
type SearchResult ¶
type SearchResult struct {
ProductID string `json:"productId"`
SKU string `json:"sku"`
Name string `json:"name"`
Price money.Centavos `json:"price"`
ListPrice money.Centavos `json:"listPrice"`
Available int `json:"available"`
Seller string `json:"seller"`
Unit string `json:"unit"`
UnitMult float64 `json:"unitMultiplier"`
}
SearchResult is one purchasable SKU.
Seller is carried per result rather than assumed from a constant: it is the value the cart API needs, and it differs per store (and in principle per item within a store).
type Session ¶
type Session struct {
AuthToken string `json:"authToken"`
OrderFormID string `json:"orderFormId"`
Email string `json:"email"`
}
Session is the storefront's view of the current visitor.
type Simulation ¶
type Simulation struct {
Items []SimulationItem `json:"items"`
LogisticsInfo []SimulationLogisticsInfo `json:"logisticsInfo"`
PaymentSystems []PaymentSystem `json:"paymentSystems"`
}
type SimulationItem ¶
type SimulationItemRequest ¶
type SimulationLogisticsInfo ¶
type SimulationLogisticsInfo struct {
SLAs []SimulationSLA `json:"slas"`
}
type SimulationSLA ¶
type SimulationSLA struct {
Name string `json:"name"`
Price money.Centavos `json:"price"`
ShippingEstimate string `json:"shippingEstimate"`
AvailableDeliveryWindows []DeliveryWindow `json:"availableDeliveryWindows"`
}
type Subscription ¶ added in v0.5.0
type Subscription struct {
ID string `json:"id"`
CustomerEmail string `json:"customerEmail"`
Title string `json:"title"`
Status string `json:"status"`
IsSkipped bool `json:"isSkipped"`
NextPurchaseDate string `json:"nextPurchaseDate"`
LastPurchaseDate string `json:"lastPurchaseDate"`
CycleCount int `json:"cycleCount"`
Plan SubscriptionPlan `json:"plan"`
Settings SubscriptionSettings `json:"purchaseSettings"`
Items []SubscriptionItem `json:"items"`
}
Subscription is one recurring order.
The address and payment method RNS reports are opaque VTEX IDs with nothing a shopper could read, so they are not surfaced. DeliveryWindow is the one human-readable part of purchaseSettings — Mantiqueira returns "Receba às terças-feiras".
type SubscriptionItem ¶ added in v0.5.0
type SubscriptionItem struct {
ID string `json:"id"`
SKU string `json:"skuId"`
Quantity int `json:"quantity"`
Status string `json:"status"`
IsSkipped bool `json:"isSkipped"`
Price money.Centavos `json:"priceAtSubscriptionDate"`
}
SubscriptionItem is one SKU in a subscription. A subscription can carry several, and each can be skipped independently of the subscription itself.
Price is the price locked in when the subscription was created, which is why it keeps the API's name rather than becoming a plain "price" — it is not today's shelf price. RNS sends it as integer centavos serialized as a float (6590.0 for R$65,90), the same encoding the OMS uses, so money.Centavos reads it correctly with no conversion.
type SubscriptionPlan ¶ added in v0.5.0
type SubscriptionSettings ¶ added in v0.5.0
type SubscriptionSettings struct {
DeliveryWindow string `json:"selectedSla"`
}
SubscriptionSettings carries the only human-readable part of the API's purchaseSettings; the rest is payment and address IDs.
type TransactionResult ¶
type Wishlist ¶ added in v0.2.0
type Wishlist struct {
Name string `json:"name"`
Public bool `json:"public"`
Items []WishlistItem `json:"items"`
}
type WishlistItem ¶ added in v0.2.0
type WishlistItem struct {
ID int `json:"id"`
ProductID string `json:"productId"`
SKU string `json:"sku"`
Title string `json:"title"`
}
WishlistItem is one saved product from the store's own wishlist.
ID is the item's position-derived identifier within the list, and it is what RemoveFromList takes — not the SKU. ProductID and SKU genuinely differ for products with variants, and AddToList wants both.