Skip to main content
Marketplaces are harder to bill than SaaS. You have two-sided fees (listing charges and final-value commissions), multi-recipient payouts, premium seller tiers, and refunds that have to ripple back through both the seller’s fees and the buyer’s payment. This guide shows how to compose Monigo’s primitives — metrics, plans, subscriptions, and events — into a working end-to-end marketplace billing layer.
The patterns here apply to most marketplaces — auction-style platforms like eBay, goods marketplaces like Etsy and Jumia, and services marketplaces. The worked example uses an eBay-style auction flow.

Mapping marketplace concepts to Monigo

Marketplace conceptMonigo primitive
SellersCustomers, tagged with metadata.role = "seller"
Listing fee per itemMetric with count aggregation, priced on a collection plan
Final-value commissionMetric with sum aggregation over a property you populate on each sale event
Seller earnings (payout)Metric with sum aggregation, priced on a payout plan
Premium seller tierA second collection plan with different pricing
Seller bank accountPayout account on the seller customer
Every seller carries two Monigo subscriptions: a collection plan that invoices them for listing fees and platform commission, and a payout plan that generates bills for their earnings. Monigo enforces this one-of-each rule at the API level — a customer can have exactly one active collection subscription and one active payout subscription at a time.

End-to-end flow


1. Create sellers as customers

Every seller is a Monigo customer. Tag them with metadata.role so your code can distinguish sellers from buyers downstream.
curl -X POST https://api.monigo.co/v1/customers \
  -H "Authorization: Bearer mk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ada Power-Seller",
    "email": "ada@example.com",
    "metadata": { "role": "seller" }
  }'

2. Register the seller’s payout account

Sellers receive their earnings into a bank account linked to the customer record. Register it before the first payout is due.
curl -X POST https://api.monigo.co/v1/customers/<seller_id>/payout-accounts \
  -H "Authorization: Bearer mk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "payout_method": "bank_transfer",
    "account_name": "Ada Power-Seller",
    "bank_name": "Access Bank",
    "bank_code": "044",
    "account_number": "0123456789",
    "currency": "NGN",
    "is_default": true
  }'
The account is looked up by currency when a payout is initiated, so set is_default: true on the seller’s primary account in each currency you pay out.

3. Define the usage metrics

Monigo bills from metrics — named aggregations over the events you ingest. A marketplace needs three:
MetricEventAggregationPurpose
listingsitem_listedcountOne unit per listing — drives the listing fee
platform_commissionitem_soldsum of commission_amount propertyTotal commission owed by the seller that period
seller_earningsitem_soldsum of seller_share propertyTotal amount the seller is owed that period
sum-aggregation metrics require an aggregation_property naming the event property that carries the numeric value. You compute the commission (10%) and seller share (90%) in your own code when the sale completes, and pass both as properties on the item_sold event.
curl -X POST https://api.monigo.co/v1/metrics \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "name": "Listings",
    "event_name": "item_listed",
    "aggregation": "count"
  }'

curl -X POST https://api.monigo.co/v1/metrics \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "name": "Platform Commission",
    "event_name": "item_sold",
    "aggregation": "sum",
    "aggregation_property": "commission_amount"
  }'

curl -X POST https://api.monigo.co/v1/metrics \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "name": "Seller Earnings",
    "event_name": "item_sold",
    "aggregation": "sum",
    "aggregation_property": "seller_share"
  }'

4. Create the fee plan and the earnings plan

A seller is billed by a collection plan (the fees you charge them) and paid by a payout plan (the earnings you owe them). Both plans point at the metrics you just defined. Collection plan — listing fee + commission:
curl -X POST https://api.monigo.co/v1/plans \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "name": "Seller Fees — Standard",
    "currency": "NGN",
    "plan_type": "collection",
    "billing_period": "monthly",
    "prices": [
      {
        "metric_id": "<listings_metric_id>",
        "model": "flat_unit",
        "unit_price": "100.000000"
      },
      {
        "metric_id": "<platform_commission_metric_id>",
        "model": "flat_unit",
        "unit_price": "1.000000"
      }
    ]
  }'
₦100 per listing, then ₦1 per unit of platform_commission. Because platform_commission sums the commission_amount property and you pass the commission in naira, one unit = ₦1 and the commission is passed through literally. Payout plan — seller earnings:
curl -X POST https://api.monigo.co/v1/plans \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "name": "Seller Earnings",
    "currency": "NGN",
    "plan_type": "payout",
    "billing_period": "monthly",
    "prices": [
      {
        "metric_id": "<seller_earnings_metric_id>",
        "model": "flat_unit",
        "unit_price": "1.000000"
      }
    ]
  }'

5. Subscribe the seller to both plans

A customer can hold at most one active collection subscription and one active payout subscription at a time. Create both:
# Charge the seller for listings and commission
curl -X POST https://api.monigo.co/v1/subscriptions \
  -H "Authorization: Bearer mk_live_..." \
  -d '{ "customer_id": "<seller_id>", "plan_id": "<seller_fees_plan_id>" }'

# Track what you owe the seller
curl -X POST https://api.monigo.co/v1/subscriptions \
  -H "Authorization: Bearer mk_live_..." \
  -d '{ "customer_id": "<seller_id>", "plan_id": "<seller_earnings_plan_id>" }'
If the seller already has an active subscription of the same plan type, the API returns 409 Conflict.

6. Ingest a listing event

Events are sent in batches to POST /v1/ingest. For each listing, send one event against item_listed:
curl -X POST https://api.monigo.co/v1/ingest \
  -H "Authorization: Bearer mk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event_name": "item_listed",
        "customer_id": "<seller_id>",
        "idempotency_key": "listing_<listing_id>",
        "timestamp": "2026-04-16T10:00:00Z",
        "properties": {
          "listing_id": "<listing_id>",
          "category": "electronics"
        }
      }
    ]
  }'
The idempotency_key must be unique per listing — resending the same key is a safe no-op. See Idempotency.
The ingest API requires an API key with the ingest scope. Create a dedicated key in Dashboard → API Keys and use it from your event-emitting services.

7. Ingest a sale event

When a buyer completes a purchase, compute the commission and seller share on your side, then ingest a single item_sold event carrying both values in its properties. One event drives two metrics:
curl -X POST https://api.monigo.co/v1/ingest \
  -H "Authorization: Bearer mk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event_name": "item_sold",
        "customer_id": "<seller_id>",
        "idempotency_key": "sale_<sale_id>",
        "timestamp": "2026-04-16T14:30:00Z",
        "properties": {
          "listing_id": "<listing_id>",
          "buyer_id": "<buyer_id>",
          "final_price": 25000,
          "commission_amount": 2500,
          "seller_share": 22500
        }
      }
    ]
  }'
For a ₦25 000 sale with a 10% commission rate:
  • platform_commission rolls up by 2 500, adding ₦2 500 to the seller’s fees invoice.
  • seller_earnings rolls up by 22 500, adding ₦22 500 to the seller’s payout bill.
Because you compute the commission split in your own code, you can change commission tiers, run promotions, or apply category-specific rates without modifying any Monigo configuration — just change the numbers you put in the event.

8. Period close and payout

At the end of each billing period, Monigo runs two jobs automatically:
  1. Invoice generation for the collection plan — a draft invoice is created with line items for listings and commission, then finalized and sent for payment on the seller’s payment method.
  2. Bill generation for the payout plan — a draft bill is created with a seller_earnings line item, then finalized.
Initiating the actual transfer of funds to the seller is a deliberate manual step today. In Dashboard → Bills, select finalized bills and click Initiate Payout. Monigo looks up the seller’s default payout account for the bill’s currency, submits the transfer via your connected payment processor, and updates the bill as the transfer settles.
There is no public API endpoint to initiate a payout programmatically at this time. Marketplaces that need fully automated payouts should subscribe to the invoice.finalized webhook for bills and process them in a scheduled dashboard session, or reach out to us about API access for bill actions.
Once the transfer is submitted, Monigo emits payout.success or payout.failed as the payment provider confirms settlement.

Premium seller tiers

Power sellers often get reduced commission in exchange for higher volume commitments. Model this as a separate collection plan — free listings and a lower commission multiplier — then move the seller onto it when they qualify.
curl -X POST https://api.monigo.co/v1/plans \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "name": "Seller Fees — Power Seller",
    "currency": "NGN",
    "plan_type": "collection",
    "billing_period": "monthly",
    "prices": [
      {
        "metric_id": "<listings_metric_id>",
        "model": "flat_unit",
        "unit_price": "0.000000"
      },
      {
        "metric_id": "<platform_commission_metric_id>",
        "model": "flat_unit",
        "unit_price": "1.000000"
      }
    ]
  }'
The commission metric unit price stays at ₦1 — your application code now computes 6% of final_price instead of 10% when populating commission_amount. This way, changing commission rates never requires touching Monigo plans. To move an existing seller onto the Power Seller plan, cancel their current collection subscription and create a new one. Their payout subscription is unaffected.
curl -X DELETE https://api.monigo.co/v1/subscriptions/<collection_subscription_id> \
  -H "Authorization: Bearer mk_live_..."

curl -X POST https://api.monigo.co/v1/subscriptions \
  -H "Authorization: Bearer mk_live_..." \
  -d '{
    "customer_id": "<seller_id>",
    "plan_id": "<power_seller_plan_id>"
  }'
See Subscription Lifecycle for how the final invoice on the old subscription is generated before the new one takes over.

Refunds and disputes

When a buyer is refunded after the billing period has closed, both the seller’s commission invoice and the seller’s payout bill may need reversing. The public API supports two operations on finalised invoices and draft bills:
  • POST /v1/invoices/<invoice_id>/void — voids an unpaid invoice. Fires invoice.voided.
  • Void bills from Dashboard → Bills before payout is initiated.
If the payout has already been transferred, the provider-side reversal path fires payout.reversed. Subscribe to this webhook and settle the clawback against the seller’s next payout in your own books. For in-period refunds (before the billing cycle closes), the simplest pattern is to subtract from the ongoing rollups by ingesting a compensating event with negative property values:
curl -X POST https://api.monigo.co/v1/ingest \
  -d '{
    "events": [{
      "event_name": "item_sold",
      "customer_id": "<seller_id>",
      "idempotency_key": "refund_<refund_id>",
      "timestamp": "2026-04-16T15:00:00Z",
      "properties": {
        "original_sale_id": "<sale_id>",
        "commission_amount": -2500,
        "seller_share": -22500
      }
    }]
  }'
The sum aggregation respects negative property values, so the rollups for platform_commission and seller_earnings drop by the refunded amount before the period closes. Use a distinct idempotency_key prefix (e.g., refund_) so refunds and sales can’t collide.

Alternative: seller-collects model

If you don’t want to be merchant of record, each seller can use their own Paystack or Flutterwave account. Buyers pay sellers directly; Monigo only bills sellers for platform fees. In this model, drop the payout plan and subscription entirely. Each seller has just a collection subscription, connects their own payment processor in the dashboard, and Monigo charges them at period end from their connected account. This is operationally simpler (no merchant-of-record obligations, no held funds, no payout step) but gives you less control over buyer experience and refund timing. Pick it when your sellers already run their own payment accounts.

Webhooks to subscribe to

EventWhat it signals
invoice.finalizedSeller’s monthly fees invoice is ready
invoice.paidSeller paid their listing + commission fees
invoice.voidedAn invoice was voided — used for refund reconciliation
payout.successA bill transfer completed successfully
payout.failedA bill transfer failed — surface to the seller and retry
payout.reversedA completed transfer was reversed by the provider
subscription.suspendedSeller was suspended after failed dunning — pause their listings
See Webhooks for payload shapes and signature verification.
  • Metering — how events become usage rollups and line items
  • Pricing Models — full reference for flat_unit, tiered, package, and other models
  • Subscription Lifecycle — pausing a seller, plan changes, cancellation
  • Event-Driven Payouts — deeper background on the collection/payout plan split
  • Idempotency — why every listing, sale, and refund needs a stable idempotency key