Integrations
Webhooks
Type definitions and reference payloads for every event the Basta platform sends. TypeScript type guards and Ruby (RBS) signatures are provided for consuming them safely.
These definitions serve as documentation and reference implementations for integrators who need to consume Basta webhooks.
Looking to set up webhooks? See Managing Webhooks for how to subscribe to events, test your endpoint, and retry failed deliveries.
Available languages
- TypeScript (
webhooks.ts) — type definitions with type guards - RBS (
webhooks.rbs) — Ruby type signatures for static type checking
Base structure
All webhooks follow the same base structure:
{
"idempotencyKey": "unique-key-for-deduplication",
"actionType": "BidOnItem",
"data": {
// Action-specific payload
}
}export type Action =
| "Unspecified"
| "BidOnItem"
| "ItemsStatusChanged"
| "SaleItemUpdated"
| "SaleStatusChanged"
| "SaleCreated"
| "SaleUpdated"
| "ItemAddedToSale"
| "SaleItemRemoved"
| "CancelBidOnItem"
| "OrderCreated"
| "OrderUpdated"
| "OrderDeleted"
| "OrderCancelled"
| "SaleRegistrationCreated"
| "SaleRegistrationUpdated"
| "SaleRegistrationDeleted"
| "SaleItemRegistrationCreated"
| "SaleItemRegistrationDeleted";
export interface BastaAction<T = unknown> {
idempotencyKey: string;
actionType: Action;
data: T;
}Action types
The following action types are currently supported:
Bidding actions
BidOnItem— A new bid was placed on an itemCancelBidOnItem— Bids were cancelled on an item
BidOnItem payload details
The BidOnItem action is sent whenever a new bid is placed on an item. Here's a detailed breakdown of the payload structure.
Core fields
| Field | Type | Description |
|---|---|---|
bidId | string | Unique identifier for this bid |
saleId | string | ID of the sale containing this item |
itemId | string | ID of the item being bid on |
userId | string | ID of the user who placed the bid |
amount | number | The actual bid amount placed (in minor currency units, e.g., cents) |
maxAmount | number | The maximum bid amount for proxy bidding (in minor currency units). Will be 0 for regular bids |
bidDate | string | ISO 8601 timestamp when the bid was placed (RFC3339 format) |
totalBids | number | Total number of bids on this item |
Bid type
The bidType field indicates the type of bid:
| Value | Description |
|---|---|
NORMAL | A standard bid placed by the user |
MAX | A maximum bid where the system will automatically bid up to the max amount |
REACTIVE | An automatic bid triggered by the proxy bidding system |
OFFER | An offer bid (for fixed-price or offer scenarios) |
Sale state
The saleState object contains the current state of bidding on the item:
{
newLeader: string; // User ID of the new leading bidder
prevLeader: string; // User ID of the previous leader (empty if first bid)
currentBidId: string; // ID of the current winning bid
currentBid: number; // Current bid amount (in minor currency units)
currentMaxBid: number; // Current max bid amount if proxy bidding is active
reserveMet: boolean; // Whether the reserve price has been met (deprecated, use reserveStatus)
}Reserve status
The reserveStatus field indicates whether the reserve price has been met:
| Value | Description |
|---|---|
NOT_MET | The reserve price has not been met yet |
MET | The reserve price has been met |
NO_RESERVE | This item has no reserve price |
Reactive bids
The reactiveBids array contains any automatic proxy bids that were triggered as a result of this bid. Each reactive bid has:
{
bidId: string; // ID of the reactive bid
userId: string; // User ID who set up the proxy bid
amount: number; // Amount of the reactive bid
maxAmount: number; // Maximum amount the user authorized
}Out bid details
The outBidDetails field (can be null) contains information about a user who was outbid by this action:
{
bidId: string; // ID of the losing bid
saleId: string; // Sale ID
itemId: string; // Item ID
userId: string; // User ID who was outbid
amount: number; // Their bid amount
maxAmount: number; // Their max bid amount (if they used proxy bidding)
bidDate: string; // When they placed their bid (RFC3339 format)
bidType: BidType; // Type of bid they placed
}Complete example
{
"idempotencyKey": "bid-12345-67890",
"actionType": "BidOnItem",
"data": {
"bidId": "bid_abc123",
"saleId": "sale_xyz789",
"itemId": "item_def456",
"userId": "user_123",
"amount": 15000,
"maxAmount": 20000,
"bidDate": "2024-03-15T14:30:00Z",
"bidType": "MAX",
"saleState": {
"newLeader": "user_123",
"prevLeader": "user_456",
"currentBidId": "bid_abc123",
"currentBid": 15000,
"currentMaxBid": 20000,
"reserveMet": true
},
"totalBids": 7,
"reactiveBids": [],
"outBidDetails": {
"bidId": "bid_xyz999",
"saleId": "sale_xyz789",
"itemId": "item_def456",
"userId": "user_456",
"amount": 14000,
"maxAmount": 14000,
"bidDate": "2024-03-15T14:25:00Z",
"bidType": "NORMAL"
},
"reserveStatus": "MET"
}
}Important notes
- All monetary amounts are in minor currency units (e.g., cents for USD, pence for GBP). Divide by 100 to get the major currency unit.
- The
bidDateis in RFC3339 format (ISO 8601) with timezone information. - When a user is outbid by a reactive bid, they will receive this webhook with
outBidDetailspopulated. - The
reactiveBidsarray will be populated if this bid triggered any automatic proxy bids.
The full BidOnItemActionPayload and its related types in TypeScript:
export type BidType = "NORMAL" | "MAX" | "REACTIVE" | "OFFER";
export type ReserveStatus = "NOT_MET" | "MET" | "NO_RESERVE";
export interface SaleState {
newLeader: string;
prevLeader: string;
currentBidId: string;
currentBid: number;
currentMaxBid: number;
reserveMet: boolean;
}
export interface ReactiveBid {
bidId: string;
userId: string;
amount: number;
maxAmount: number;
}
export interface OutBidDetails {
bidId: string;
saleId: string;
itemId: string;
userId: string;
amount: number;
maxAmount: number;
bidDate: string;
bidType: BidType;
}
export interface BidOnItemActionPayload {
bidId: string;
saleId: string;
itemId: string;
userId: string;
amount: number;
maxAmount: number;
bidDate: string;
bidType: BidType;
saleState: SaleState;
totalBids: number;
reactiveBids: ReactiveBid[];
outBidDetails: OutBidDetails | null;
reserveStatus: ReserveStatus;
}Item actions
ItemAddedToSale— An item was added to a saleSaleItemRemoved— An item was removed from a saleSaleItemUpdated— Item details were updatedItemsStatusChanged— Item status changed (e.g., open, closing, closed)
Sale actions
SaleCreated— A new sale was createdSaleUpdated— Sale details were updatedSaleStatusChanged— Sale status changed (e.g., published, open, closed)
Order actions
OrderCreated— A new order was createdOrderUpdated— Order details were updatedOrderDeleted— An order was deletedOrderCancelled— An order was cancelled
Registration actions
SaleRegistrationCreated— User registered for a saleSaleRegistrationUpdated— Registration was updatedSaleRegistrationDeleted— Registration was deletedSaleItemRegistrationCreated— User registered for a specific itemSaleItemRegistrationDeleted— Item registration was deleted
Usage examples
TypeScript
Each action has a matching typed alias (e.g. BidOnItemAction) and a helper type guard so you can narrow the payload:
import { BastaAction, isBidOnItemAction, BidOnItemActionPayload } from './webhooks';
function handleWebhook(webhook: BastaAction) {
if (isBidOnItemAction(webhook)) {
// TypeScript now knows webhook.data is BidOnItemActionPayload
console.log(`Bid placed: ${webhook.data.bidId}`);
console.log(`Amount: ${webhook.data.amount}`);
}
}Ruby (with RBS)
# In your Gemfile:
# gem 'rbs'
# gem 'steep' # for type checking
# sig/webhooks.rbs contains the type signatures
webhook_data = JSON.parse(request.body.read)
action = BastaWebhooks::BastaAction.new(
idempotency_key: webhook_data['idempotencyKey'],
action_type: webhook_data['actionType'],
data: webhook_data['data']
)
case action.action_type
when 'BidOnItem'
# Type checker will understand the structure
payload = BastaWebhooks::BidOnItemActionPayload.new(**action.data.symbolize_keys)
puts "Bid placed: #{payload.bid_id}"
puts "Amount: #{payload.amount}"
endTo use RBS for type checking:
# Validate RBS syntax
rbs validate
# Type check with Steep
steep checkFor questions about webhooks or to report issues with type definitions, email us at hi@basta.app.