# Marketplace & Resale

TicketConnect runs a built-in **secondary market** so your customers can resell
tickets they can no longer use — safely, at a fair price, and with you earning a
royalty on every resale. This guide covers how to **read** that market from the
API: list the active resale listings for an event and fetch a single listing.

> **You don't operate the resale checkout.** Listing a ticket for resale, taking
> the buyer's payment, transferring the ticket, and splitting the proceeds are all
> handled by the platform. From the API you read the live listings; the purchase
> and settlement happen on the platform side.


## Scopes

The read endpoints on this page require the **`marketplace:read`** scope.

| Endpoint | Method | Scope |
| --- | --- | --- |
| `/v1/marketplace/listings` | `GET` | `marketplace:read` |
| `/v1/marketplace/listings/{id}` | `GET` | `marketplace:read` |

## How resale works (at a glance)

* **Fiat pricing.** Every listing is priced in your settlement currency. You see
  one number — the resale price — just like any other amount in the API.
* **Automatic royalties.** When a listing sells, your configured royalty is taken
  out and credited to you automatically. You don't compute or collect it; it
  simply shows up in your [balance](#payouts).
* **Anti-scalping, on by default.** Every event ships with anti-scalping
  enforced and a resale ceiling of 150% of face value. Both the bounds
  (floor/ceiling), the resale-open window, and whether resale or anti-scalping
  is on at all are **per-event settings** you control when you create or update
  the event (`marketplace_settings` on [Events](#api-events)) — the same
  controls organizers get in the panel. Enforcement itself is automatic and
  can't be bypassed by a reseller; you tune the policy, the platform applies it.

Because of all this, the listing objects you read are intentionally lean: a
listing id, the ticket it belongs to, and the fiat price. No internal seller or
settlement details are ever exposed.

## List listings

Returns your resale listings, newest first, cursor-paginated via `limit` and
`starting_after`. Each listing carries its `status`, so you can pick out the
`active` ones.

```bash
curl "https://api.ticketconnect.example/v1/marketplace/listings?limit=20" \
  -H "Authorization: Bearer sk_test_..."
```

```json
{
  "object": "list",
  "data": [
    {
      "id": "list_9a3f1c2e4b6d8f0a1b2c3d4e5f60718",
      "ticket_id": "tkt_8f2c...",
      "price": 75.00,
      "currency": "USD",
      "status": "active",
      "created_at": "2026-06-05T12:00:00.000Z"
    }
  ],
  "has_more": false
}
```

To page through more results, use `starting_after` on the next request:

```bash
curl "https://api.ticketconnect.example/v1/marketplace/listings?limit=20&starting_after=list_9a3f1c2e4b6d8f0a1b2c3d4e5f60718" \
  -H "Authorization: Bearer sk_test_..."
```

> **Note:** A listing's `status` tells you where it is in its life. Once a listing sells, it
> stops being `active` and you'll receive a `marketplace.sale.completed` webhook —
> see [Webhooks](#webhooks). Use `ticket_id` to tie a listing back to the ticket
> (`GET /v1/tickets/:id`) and, through it, the event.


## Retrieve a single listing

```bash
curl https://api.ticketconnect.example/v1/marketplace/listings/list_9a3f1c2e4b6d8f0a1b2c3d4e5f60718 \
  -H "Authorization: Bearer sk_test_..."
```

```json
{
  "id": "list_9a3f1c2e4b6d8f0a1b2c3d4e5f60718",
  "ticket_id": "tkt_8f2c...",
  "price": 75.00,
  "currency": "USD",
  "status": "active",
  "created_at": "2026-06-05T12:00:00.000Z"
}
```

A listing id that doesn't exist (or isn't yours) returns `404` with a
`resource_missing` error.

## See also

* [Webhooks](#webhooks) — listen for `marketplace.sale.completed` and
  `ticket.transferred`.
* [Payouts](#payouts) — resale royalties land in your balance.
* [API reference](#api-overview) — full endpoint details.
