Skip to main content

Distributions API

Distributions are the mechanisms for allocating access to products within an experience. Fanfare supports three distribution types: Queues (first-come, first-served), Draws (lottery/raffle), and Auctions (competitive bidding).

Distribution Types Overview

TypeMechanismUse Case
QueueFirst-comeProduct launches, limited releases
DrawRandom selectionRaffles, fair allocation, high-demand items
AuctionHighest bidderCollectibles, unique items, premium access

Queues

Queues provide first-come, first-served access to products.

Create Queue

POST /api/v1/queues

Authentication

  • Secret key required

Request Body

interface CreateQueueRequest {
  sequenceId: string;
  name?: string;
  timeZone?: string;
  openAt?: string; // ISO 8601 datetime
  closeAt?: string; // ISO 8601 datetime
  encryptionSeed?: string;
  maxCapacity?: number;
  admissionRate?: number; // Consumers admitted per minute
  sessionDurationSeconds?: number;
  metadata?: Record<string, unknown>;
}

Response

interface Queue {
  id: string;
  organizationId: string;
  sequenceId: string;
  name: string | null;
  timeZone: string;
  status: "DRAFT" | "SCHEDULED" | "OPEN" | "CLOSED" | "COMPLETED";
  openAt: string | null;
  closeAt: string | null;
  encryptionSeed: string;
  maxCapacity: number | null;
  admissionRate: number | null;
  sessionDurationSeconds: number | null;
  metadata: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
}

Example

curl -X POST https://admin.fanfare.io/api/v1/queues \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "sequenceId": "seq_01HXYZ123456789",
    "name": "Launch Day Queue",
    "timeZone": "America/New_York",
    "openAt": "2024-12-15T09:00:00-05:00",
    "closeAt": "2024-12-15T18:00:00-05:00",
    "maxCapacity": 10000,
    "admissionRate": 100,
    "sessionDurationSeconds": 900
  }'
Response:
{
  "id": "queue_01HXYZ123456789",
  "organizationId": "org_01HXYZ123456789",
  "sequenceId": "seq_01HXYZ123456789",
  "name": "Launch Day Queue",
  "timeZone": "America/New_York",
  "status": "SCHEDULED",
  "openAt": "2024-12-15T14:00:00Z",
  "closeAt": "2024-12-15T23:00:00Z",
  "encryptionSeed": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "maxCapacity": 10000,
  "admissionRate": 100,
  "sessionDurationSeconds": 900,
  "metadata": null,
  "createdAt": "2024-12-01T10:00:00Z",
  "updatedAt": "2024-12-01T10:00:00Z"
}

List Queues

GET /api/v1/queues
curl -X GET https://admin.fanfare.io/api/v1/queues \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx"

Get Queue

GET /api/v1/queues/:id
curl -X GET https://admin.fanfare.io/api/v1/queues/queue_01HXYZ123456789 \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx"

Update Queue

PUT /api/v1/queues/:id
interface UpdateQueueRequest {
  name?: string;
  timeZone?: string;
  openAt?: string;
  closeAt?: string;
  maxCapacity?: number | null;
  admissionRate?: number | null;
  sessionDurationSeconds?: number | null;
  metadata?: Record<string, unknown> | null;
}
curl -X PUT https://admin.fanfare.io/api/v1/queues/queue_01HXYZ123456789 \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "admissionRate": 150,
    "closeAt": "2024-12-15T20:00:00-05:00"
  }'

Delete Queue

DELETE /api/v1/queues/:id
curl -X DELETE https://admin.fanfare.io/api/v1/queues/queue_01HXYZ123456789 \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx"

Draws

Draws (lotteries) provide random selection from a pool of entrants.

Create Draw

POST /api/v1/draws

Request Body

interface CreateDrawRequest {
  sequenceId: string;
  name?: string;
  timeZone?: string;
  openAt?: string; // Entry period starts
  closeAt?: string; // Entry period ends
  drawAt: string; // Required: When winners are selected
  winnerCount: number; // Required: Number of winners
  encryptionSeed?: string;
  maxEntries?: number;
  metadata?: Record<string, unknown>;
}

Response

interface Draw {
  id: string;
  organizationId: string;
  sequenceId: string;
  name: string | null;
  timeZone: string;
  status: "DRAFT" | "SCHEDULED" | "OPEN" | "CLOSED" | "DRAWN" | "COMPLETED";
  openAt: string | null;
  closeAt: string | null;
  drawAt: string;
  winnerCount: number;
  encryptionSeed: string;
  maxEntries: number | null;
  metadata: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
}

Example

curl -X POST https://admin.fanfare.io/api/v1/draws \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "sequenceId": "seq_01HXYZ123456789",
    "name": "Holiday Raffle",
    "timeZone": "America/New_York",
    "openAt": "2024-12-01T00:00:00-05:00",
    "closeAt": "2024-12-14T23:59:59-05:00",
    "drawAt": "2024-12-15T12:00:00-05:00",
    "winnerCount": 100,
    "maxEntries": 50000
  }'
Response:
{
  "id": "draw_01HXYZ123456789",
  "organizationId": "org_01HXYZ123456789",
  "sequenceId": "seq_01HXYZ123456789",
  "name": "Holiday Raffle",
  "timeZone": "America/New_York",
  "status": "SCHEDULED",
  "openAt": "2024-12-01T05:00:00Z",
  "closeAt": "2024-12-15T04:59:59Z",
  "drawAt": "2024-12-15T17:00:00Z",
  "winnerCount": 100,
  "encryptionSeed": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "maxEntries": 50000,
  "metadata": null,
  "createdAt": "2024-12-01T10:00:00Z",
  "updatedAt": "2024-12-01T10:00:00Z"
}

List Draws

GET /api/v1/draws

Get Draw

GET /api/v1/draws/:id

Update Draw

PUT /api/v1/draws/:id
interface UpdateDrawRequest {
  name?: string;
  timeZone?: string;
  openAt?: string;
  closeAt?: string;
  drawAt?: string;
  winnerCount?: number;
  maxEntries?: number | null;
  metadata?: Record<string, unknown> | null;
}

Delete Draw

DELETE /api/v1/draws/:id

Auctions

Auctions allow competitive bidding for products.

Create Auction

POST /api/v1/auctions

Request Body

interface CreateAuctionRequest {
  sequenceId: string;
  name?: string;
  timeZone?: string;
  openAt?: string; // Bidding starts
  closeAt?: string; // Bidding ends
  settleAt: string; // Required: When auction settles
  startingBid?: number;
  minimumIncrement?: number;
  reservePrice?: number;
  buyNowPrice?: number;
  encryptionSeed?: string;
  metadata?: Record<string, unknown>;
}

Response

interface Auction {
  id: string;
  organizationId: string;
  sequenceId: string;
  name: string | null;
  timeZone: string;
  status: "DRAFT" | "SCHEDULED" | "OPEN" | "CLOSED" | "SETTLED";
  openAt: string | null;
  closeAt: string | null;
  settleAt: string;
  startingBid: number | null;
  minimumIncrement: number | null;
  reservePrice: number | null;
  buyNowPrice: number | null;
  encryptionSeed: string;
  metadata: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
}

Example

curl -X POST https://admin.fanfare.io/api/v1/auctions \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "sequenceId": "seq_01HXYZ123456789",
    "name": "Rare Collectible Auction",
    "timeZone": "America/New_York",
    "openAt": "2024-12-10T09:00:00-05:00",
    "closeAt": "2024-12-15T21:00:00-05:00",
    "settleAt": "2024-12-15T21:30:00-05:00",
    "startingBid": 100,
    "minimumIncrement": 10,
    "reservePrice": 500,
    "buyNowPrice": 2000
  }'
Response:
{
  "id": "auction_01HXYZ123456789",
  "organizationId": "org_01HXYZ123456789",
  "sequenceId": "seq_01HXYZ123456789",
  "name": "Rare Collectible Auction",
  "timeZone": "America/New_York",
  "status": "SCHEDULED",
  "openAt": "2024-12-10T14:00:00Z",
  "closeAt": "2024-12-16T02:00:00Z",
  "settleAt": "2024-12-16T02:30:00Z",
  "startingBid": 100,
  "minimumIncrement": 10,
  "reservePrice": 500,
  "buyNowPrice": 2000,
  "encryptionSeed": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "metadata": null,
  "createdAt": "2024-12-01T10:00:00Z",
  "updatedAt": "2024-12-01T10:00:00Z"
}

List Auctions

GET /api/v1/auctions

Get Auction

GET /api/v1/auctions/:id

Update Auction

PUT /api/v1/auctions/:id
interface UpdateAuctionRequest {
  name?: string;
  timeZone?: string;
  openAt?: string;
  closeAt?: string;
  settleAt?: string;
  startingBid?: number | null;
  minimumIncrement?: number | null;
  reservePrice?: number | null;
  buyNowPrice?: number | null;
  metadata?: Record<string, unknown> | null;
}

Delete Auction

DELETE /api/v1/auctions/:id

Distribution Status

Distributions go through the following status lifecycle:

Queue Status

DRAFT → SCHEDULED → OPEN → CLOSED → COMPLETED
StatusDescription
DRAFTQueue created but no times set
SCHEDULEDOpen/close times set, waiting to open
OPENAccepting entries, admitting consumers
CLOSEDNo longer accepting entries
COMPLETEDAll admitted consumers completed

Draw Status

DRAFT → SCHEDULED → OPEN → CLOSED → DRAWN → COMPLETED
StatusDescription
DRAFTDraw created but no times set
SCHEDULEDTimes set, waiting for entry period
OPENAccepting entries
CLOSEDEntry period ended, awaiting draw
DRAWNWinners selected
COMPLETEDAll winners have claimed or expired

Auction Status

DRAFT → SCHEDULED → OPEN → CLOSED → SETTLED
StatusDescription
DRAFTAuction created but no times set
SCHEDULEDTimes set, waiting for bidding to start
OPENAccepting bids
CLOSEDBidding ended, awaiting settlement
SETTLEDWinner confirmed, payment processed

Timing Configuration

Time Zones

All distributions support time zone configuration:
{
  "timeZone": "America/New_York",
  "openAt": "2024-12-15T09:00:00", // Interpreted as 9 AM Eastern
  "closeAt": "2024-12-15T18:00:00" // Interpreted as 6 PM Eastern
}
If no time zone is specified, the organization’s default time zone is used.

Scheduling Events

When timing fields (openAt, closeAt, drawAt, settleAt) are updated, distribution update events are automatically published for processing.

Common Fields

All distribution types share these common fields:
FieldTypeDescription
idstringUnique distribution ID
organizationIdstringOwning organization
sequenceIdstringParent sequence/experience
namestringDisplay name
timeZonestringIANA time zone
statusstringCurrent status
openAtstring (ISO 8601)When participation opens
closeAtstring (ISO 8601)When participation closes
encryptionSeedstringSeed for consumer position encoding
metadataobjectCustom metadata
createdAtstring (ISO 8601)Creation timestamp
updatedAtstring (ISO 8601)Last update timestamp

Error Responses

StatusErrorDescription
400Validation failedInvalid request data
401Authentication requiredMissing or invalid credentials
404Queue/Draw/Auction not foundDistribution does not exist
409Cannot update closed distributionDistribution already closed

SDK Usage

import { FanfareAdmin } from "@fanfare/admin-sdk";

const admin = new FanfareAdmin({
  secretKey: process.env.FANFARE_SECRET_KEY,
});

// Create queue
const queue = await admin.queues.create({
  sequenceId: "seq_01HXYZ",
  name: "Product Launch",
  openAt: "2024-12-15T09:00:00-05:00",
  closeAt: "2024-12-15T18:00:00-05:00",
  admissionRate: 100,
});

// List queues
const queues = await admin.queues.list();

// Update queue
await admin.queues.update(queue.id, {
  admissionRate: 150,
});

// Create draw
const draw = await admin.draws.create({
  sequenceId: "seq_01HXYZ",
  name: "Holiday Raffle",
  openAt: "2024-12-01T00:00:00Z",
  closeAt: "2024-12-14T23:59:59Z",
  drawAt: "2024-12-15T12:00:00Z",
  winnerCount: 100,
});

// Create auction
const auction = await admin.auctions.create({
  sequenceId: "seq_01HXYZ",
  name: "Rare Item Auction",
  openAt: "2024-12-10T09:00:00Z",
  closeAt: "2024-12-15T21:00:00Z",
  settleAt: "2024-12-15T21:30:00Z",
  startingBid: 100,
  minimumIncrement: 10,
});

// Delete distribution
await admin.queues.delete(queue.id);
await admin.draws.delete(draw.id);
await admin.auctions.delete(auction.id);