> ## Documentation Index
> Fetch the complete documentation index at: https://docs.digitalseaservice.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sponsorship API

> Partner-only endpoints for provisioning and managing sponsored Premium seats. Requires a sponsorship program.

<Note>
  **Restricted — requires a sponsorship program.** These endpoints are only
  available to partners who run a DSS sponsorship program. If you don't have one
  and want one, [contact DSS](mailto:admin@digitalseaservice.com). The rest of
  the API (OAuth, `/v1/me/*`, webhooks) needs no program.
</Note>

A **sponsorship program** lets a partner pay for Premium on behalf of their
crew. You provision a crew member into a **seat**; DSS creates (or reuses) the
account, attaches the vessel, turns on Premium, and bills the seat back to you
on a recurring basis. The member is provisioned just-in-time and is Premium
immediately.

## Base path & authentication

All partner endpoints live under `/v1/partners/` and authenticate with **HTTP
Basic**, not the OAuth bearer flow the rest of the API uses. Send your partner
`client_id` as the username and `client_secret` as the password:

```http theme={null}
POST /v1/partners/sponsorships HTTP/1.1
Host: api.digitalseaservice.com
Authorization: Basic <base64(client_id:client_secret)>
Content-Type: application/json
```

```bash theme={null}
curl -u "$DSS_CLIENT_ID:$DSS_CLIENT_SECRET" \
  https://api.digitalseaservice.com/v1/partners/sponsorships
```

<Warning>
  The `client_secret` is a bearer-equivalent credential for your whole program —
  anyone holding it can provision and remove seats. Store it in a secret manager,
  never in source control, and rotate it with DSS if it leaks. Bad or missing
  Basic credentials return [`invalid_token` (401)](/errors/invalid_token); a
  suspended partner returns [`insufficient_scope` (403)](/errors/insufficient_scope).
</Warning>

## Endpoints

| Method & path                           | Purpose                                                   |
| --------------------------------------- | --------------------------------------------------------- |
| `POST /v1/partners/sponsorships`        | [Provision a seat](/sponsorships/provision)               |
| `GET /v1/partners/sponsorships`         | [List your roster](/sponsorships/reconciliation)          |
| `GET /v1/partners/sponsorships/{id}`    | [Get one seat](/sponsorships/reconciliation#get-one-seat) |
| `DELETE /v1/partners/sponsorships/{id}` | [Remove a seat](/sponsorships/remove)                     |

Every response is a **public projection** of a seat. Internal fields — such as
the Stripe subscription-item id — never cross this boundary.

## Seat lifecycle

A seat moves through a small set of states. You'll see these in the `status`
field of every response.

| Status      | Meaning                                                                                                                                                                                                    | Premium?        | Occupies a seat? |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ---------------- |
| `active`    | Provisioned. Entitlement granted; the seat is billed to you.                                                                                                                                               | Yes             | Yes              |
| `converted` | The member started paying for themselves (added their own card, e.g. at the end of the sponsorship term), so the seat leaves your subscription — you get a prorated credit — and the member keeps Premium. | Yes (self-paid) | No               |
| `cancelled` | You removed the seat, or it was removed for GDPR/admin reasons.                                                                                                                                            | No              | No               |
| `expired`   | The per-member term elapsed with no self-pay card; the member was downgraded to Free.                                                                                                                      | No              | No               |

`active` is the only status that **occupies your billable seat**. `converted`,
`cancelled` and `expired` do not.

## Billing model

* Each **active** seat is invoiced to the partner on a recurring basis, for as
  long as it stays active.
* **Removing** a seat (or a member converting to self-pay) issues a **prorated
  credit** to the partner for the unused remainder of that seat's period.
* Billing is **partner-facing only**. An unpaid partner invoice never downgrades
  a crew member before their own term ends — the member keeps Premium for the
  term you provisioned, and billing disputes are settled partner-to-DSS.
* The per-member sponsored **term** (see `expires_at`) is independent of your
  invoice cadence: it starts when the seat activates and runs for the program's
  configured term length.

<Note>
  Commercial terms — the per-seat rate, invoice cadence, and settlement terms —
  are covered in your program agreement, not in these docs.
</Note>

## Idempotency

Provisioning is **idempotent per email within your program**. Re-sending the
same member never creates a second seat or a second bill — you get the existing
open seat back with `200` instead of `201`. See
[Provision a seat](/sponsorships/provision#idempotency) for the `Idempotency-Key`
header and the exact replay semantics.

## Webhooks

There are **no partner-subscribable webhook events for sponsorship seats** in
V1. Reconcile seat state by polling
[`GET /v1/partners/sponsorships`](/sponsorships/reconciliation) on a schedule.
The webhook [events catalogue](/webhooks/events) covers the `user.*` events only,
which are delivered against OAuth scopes and are unrelated to sponsorship
billing.

## Related

* [Provision a seat](/sponsorships/provision)
* [Reconcile your roster](/sponsorships/reconciliation)
* [Remove a seat](/sponsorships/remove)
* [Errors overview](/errors)
