This directory contains type definitions for all webhooks/actions sent by the Basta platform.
These files serve as documentation and reference implementations for integrators who need to consume Basta webhooks.
- TypeScript (
webhooks.ts) - Type definitions with type guards - RBS (
webhooks.rbs) - Ruby type signatures for static type checking
All webhooks follow the same base structure:
{
"idempotencyKey": "unique-key-for-deduplication",
"actionType": "BidOnItem",
"data": {
// Action-specific payload
}
}The following action types are currently supported:
BidOnItem- A new bid was placed on an itemCancelBidOnItem- Bids were cancelled on an item
The BidOnItem action is sent whenever a new bid is placed on an item. Here's a detailed breakdown of the payload structure:
| 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 |
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) |
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)
}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 |
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
}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
}{
"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.
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)
SaleCreated- A new sale was createdSaleUpdated- Sale details were updatedSaleStatusChanged- Sale status changed (e.g., published, open, closed)
OrderCreated- A new order was createdOrderUpdated- Order details were updatedOrderDeleted- An order was deletedOrderCancelled- An order was cancelled
SaleRegistrationCreated- User registered for a saleSaleRegistrationUpdated- Registration was updatedSaleRegistrationDeleted- Registration was deletedSaleItemRegistrationCreated- User registered for a specific itemSaleItemRegistrationDeleted- Item registration was deleted
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}`);
}
}# 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: hi@basta.app
- Documentation: docs.basta.ai