# Sponsor MMB (/docs/sponsorships)



MMB offers a founding website sponsorship for $99 for four consecutive weeks, bookable through November 4, 2026 (UTC). Renewals are quoted separately. YouTube integrations are coming soon; YouTube and combined packages cannot be booked. Inventory returns `durationWeeks`, `comingSoon`, and `offerEndsAt` alongside the total package price in the legacy `weekPriceCents` field. A booking atomically reserves every week of its duration.

[Open the partner studio](/sponsors) to explore availability, prepare creative, and review results. The [admin studio](/admin) handles creative review, pricing, payment reconciliation, and refunds.

## Start with the right access [#start-with-the-right-access]

Sign in with a verified account, open **API access** in the [management workspace](/sponsors/manage), and create a named key with the scopes your integration needs. Save the key when it is shown. MMB stores its hash and displays only the prefix afterward.

| Scope           | What it allows                                                                                                           |
| --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `library:read`  | Bot templates, use cases, and library usage.                                                                             |
| `sponsor:read`  | Your profile, campaigns, bookings, receipts, and reporting.                                                              |
| `sponsor:write` | Your profile and draft creative; submitting creative for review.                                                         |
| `billing:write` | Reserving a week, starting checkout, cancelling unpaid bookings, for sponsorships.                                       |
| `keys:manage`   | Listing, creating, and revoking your keys. A new key can only receive scopes held by the calling credential.             |
| `admin:read`    | Studio overview, sponsors, creative, inventory, bookings, and activity. Requires current admin membership.               |
| `admin:write`   | Creative review, slot changes, refunds, payment reconciliation, and YouTube delivery. Requires current admin membership. |

Existing library keys retain library access. Create an explicitly scoped key for sponsorship operations. Admin scopes also require the verified account to remain in the admin allowlist. Each resource request checks account ownership.

Set `MMB_BASE_URL` to the deployment you are using and keep `MMB_API_KEY` in your secret store. A preview uses its own URL, accounts, and database.

```bash
curl "$MMB_BASE_URL/api/v1/sponsors/me" \
  -H "Authorization: Bearer $MMB_API_KEY"
```

## The short booking flow [#the-short-booking-flow]

`POST /api/v1/sponsors/bookings/start` saves the sponsor profile, creates submitted creative, and reserves the selected package in one transaction. It requires both `sponsor:write` and `billing:write`.

```json
{
  "name": "Example Studio",
  "website": "https://example.com",
  "headline": "Build something useful.",
  "body": "Practical tools for the next thing you build.",
  "slotId": "PACKAGE_ID_FROM_INVENTORY",
  "weekStart": 1788739200000,
  "idempotencyKey": "A_FRESH_UUID"
}
```

Use a currently available Monday from inventory. The response contains `booking`. Call its checkout endpoint and open the returned Stripe URL. Identical retries return the same booking; changed details require a new UUID. A capacity conflict rolls back the profile and creative changes.

The individual operations below are available for integrations that need finer control.

## 1. Introduce your company [#1-introduce-your-company]

```bash
curl -X PATCH "$MMB_BASE_URL/api/v1/sponsors/profile" \
  -H "Authorization: Bearer $MMB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example Studio","website":"https://example.com"}'
```

## 2. Create and submit your creative [#2-create-and-submit-your-creative]

Campaigns use a short headline, introduction, initials, destination, and button label. The studio previews the same component used in the public rail.

```bash
curl -X POST "$MMB_BASE_URL/api/v1/sponsors/campaigns" \
  -H "Authorization: Bearer $MMB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Our next chapter","headline":"Something worth discovering.","body":"Meet the tools that make room for your next good idea.","cta":"Take a closer look","targetUrl":"https://example.com","logoText":"ES"}'

curl -X POST "$MMB_BASE_URL/api/v1/sponsors/campaigns/$CAMPAIGN_ID/submit" \
  -H "Authorization: Bearer $MMB_API_KEY" \
  -H "Content-Type: application/json" -d '{}'
```

New campaigns start as `draft`. Submitted creative becomes `pending`. Admins can approve it or return it with a review note. Submitted and approved creative is locked; create a new campaign when you want a different introduction. Drafts and rejected creative can be edited through `PATCH /api/v1/sponsors/campaigns/{id}`.

## 3. Find an available week [#3-find-an-available-week]

```bash
curl "$MMB_BASE_URL/api/v1/sponsors/inventory"
```

Inventory is public. It returns slot IDs, availability, weekly prices in USD cents, the billing mode, and the next full week's boundaries. Pass `weekStart` as UTC epoch milliseconds to choose another Monday in the next 26 weeks.

Once your creative is submitted, reserve an available package. Creative review happens after booking and before delivery. Supply a fresh UUID for each intended booking and reuse that same UUID when retrying the request.

```bash
curl -X POST "$MMB_BASE_URL/api/v1/sponsors/bookings" \
  -H "Authorization: Bearer $MMB_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"campaignId\":\"$CAMPAIGN_ID\",\"slotId\":\"$SLOT_ID\",\"weekStart\":$WEEK_START,\"idempotencyKey\":\"$BOOKING_UUID\"}"
```

The server records the current price and reserves the week in one transaction. Concurrent requests converge on one owner. Reusing a UUID with different booking details returns `409 idempotency_conflict`. An occupied week returns `409 slot_unavailable`.

## 4. Complete payment [#4-complete-payment]

```bash
curl -X POST "$MMB_BASE_URL/api/v1/sponsors/bookings/$BOOKING_ID/checkout" \
  -H "Authorization: Bearer $MMB_API_KEY" \
  -H "Content-Type: application/json" -d '{}'
```

Open the returned Stripe Checkout URL to pay. Repeating the request resumes the same payment session. A verified payment confirms the booking. The return page refreshes payment status; the signed Stripe webhook and scheduled reconciliation also record completion.

Reservations initially last 40 minutes. Starting checkout establishes a 35-minute payment window. Recovery can extend the hold while the provider's state is being checked. If a request fails, retry the same booking. Its `paymentIssue` explains any outstanding recovery. Unpaid reservations can be cancelled through `POST /api/v1/sponsors/bookings/{id}/cancel` with an empty JSON object.

## 5. Follow the introduction [#5-follow-the-introduction]

`GET /api/v1/sponsors/bookings` lists your bookings, receipts, refunds, and delivery counts. Pass `cursor` from the previous response to continue; `limit` defaults to 20 and is capped at 50. Campaign and admin lists use the same pagination.

Only paid bookings with approved creative and an active slot appear during their booked week. A paused campaign stops delivery immediately. Test placements are visible only in preview deployments.

Reporting counts a browser's first visible impression and click per booking per UTC day. Impressions require at least half the card to be visible. Counts are best-effort analytics, affected by browser settings and repeat visits across devices; they are not audited billing measurements. Event identifiers are hashed and expire after two days.

## The admin workflow [#the-admin-workflow]

Admin clients use the same bearer authentication with current admin membership:

| Action                    | Endpoint                                                     |
| ------------------------- | ------------------------------------------------------------ |
| Overview                  | `GET /api/v1/admin/sponsorships/overview`                    |
| Review queue              | `GET /api/v1/admin/sponsorships/campaigns`                   |
| Approve, reject, or pause | `POST /api/v1/admin/sponsorships/campaigns/{id}/review`      |
| Bookings and reporting    | `GET /api/v1/admin/sponsorships/bookings`                    |
| Sponsors                  | `GET /api/v1/admin/sponsorships/sponsors`                    |
| Inventory                 | `GET /api/v1/admin/sponsorships/slots`                       |
| Price and availability    | `PATCH /api/v1/admin/sponsorships/slots/{id}`                |
| Full refund               | `POST /api/v1/admin/sponsorships/bookings/{id}/refund`       |
| YouTube delivery          | `PATCH /api/v1/admin/sponsorships/bookings/{id}/fulfillment` |
| Payment recovery          | `POST /api/v1/admin/sponsorships/bookings/{id}/reconcile`    |
| Activity log              | `GET /api/v1/admin/sponsorships/audit`                       |

YouTube fulfillment accepts `youtubeStatus` (`planned` or `published`), `youtubeNotes`, and an optional `youtubeUrl`. Publishing requires a valid YouTube video URL and a paid YouTube or combined booking. Sponsor booking responses include the status, URL, and notes.

A review requires a `decision` (`approved`, `rejected`, or `paused`) and a useful `note`. A refund requires a `reason`. Price edits affect new reservations. Turning a slot off pauses public delivery while preserving existing bookings.

Successful full refunds release the week. Partial refunds issued in Stripe are reflected in the ledger and leave delivery active. Reconciliation queues a durable provider check and returns `{ "scheduled": true }`; refresh the booking afterward. Payment and administrative events are written to the activity log.

## Preview and live operation [#preview-and-live-operation]

The combined preview includes sample sponsor and admin accounts, editable example prices, and a clearly marked sample placement. Seeded bookings have no charge. A new booking uses Stripe test-mode Checkout when the deployment's test key is configured.

Live operation requires live Stripe credentials, a signed webhook, an admin allowlist, and confirmed prices. Every booking stores its billing mode. Preview calls always select test mode, and production never serves test placements.

## Errors and the complete contract [#errors-and-the-complete-contract]

`400` indicates invalid input; `401` an absent or revoked credential; `403` a missing scope, ownership role, or account verification; `404` an unavailable resource; `409` a booking or workflow conflict; `429` a rate limit; and `503` a payment configuration or recovery issue.

All request bodies are strict JSON objects. Browser sessions require same-origin mutations; bearer clients work headlessly. [The API reference](/docs/api-reference) contains every schema and endpoint. [OpenAPI JSON](/openapi.json) is generated from the same request contract. Append `.md` to this page URL for a version your agent can read.
