Skip to main content

Organizations

Organizations let partners manage teams of athletes under a single billing structure. This is designed for coaching platforms, team managers, and enterprise partners who onboard athletes in groups. The examples read your key from a SATURDAY_API_KEY environment variable, as in Quickstart. Sandbox keys are issued with their own base URL; using one against api.saturday.fit returns 401 invalid_api_key.

Creating an organization

The response includes server-set id, created_at, updated_at, and a maintained member_count.

Managing members

Members are the organization’s people directory: coaches and staff, keyed by email. They are separate from athlete records, and linking a member row to an athlete via athlete_id is optional.

Adding members

Member roles

Any other value returns 400.

Listing and removing members

Removing a member never deletes an athlete profile; it removes the directory entry and decrements member_count.

Seat subscriptions (team licensing)

A seat subscription is a block of paid seats the organization holds; assigning a license to an athlete grants them full-precision API responses while the subscription is active and in its date window. This is the lane for orgs that pay for their athletes’ access directly (vs. athletes paying at personal checkout).

Create a seat block

type is "team" or "enterprise"; dates are unix seconds (end_date optional). The response includes used_seats (starts at 0) and status. Manage with GET /v1/organizations/{org_id}/subscriptions and PATCH .../subscriptions/{sub_id} (update seats, status, end_date).

Assign licenses to athletes

athlete_id is required per license (email/name are display metadata); the seat limit is enforced. The licensed athlete’s next API call returns full precision. GET .../licenses lists assignments; DELETE .../licenses/{athlete_id} frees the seat (access degrades on the athlete’s next call).

Organization offers (negotiated discounts)

A coach or team admin can negotiate a discount their athletes receive at personal checkout, as in “Team Alpine athletes get 15% off Saturday.” You record it as the organization’s offer, and Saturday applies it automatically when an affiliated athlete follows a subscribe CTA from your app. Each organization has at most one active offer. PUT creates or replaces it. Previous offers are deactivated rather than deleted, so the document trail is the negotiation audit log.

Setting the offer

The response echoes the stored offer plus stack_cap_percent, the hard ceiling on the total stacked discount (currently 30).

Reading and removing the offer

Which athletes get it

The offer applies to athletes whose org_id field references this organization. Assert it when creating or updating the athlete:
org_id is partner-asserted, the same trust posture as partner_plan, and the organization must already exist: pointing at an org you have not created returns 400 rather than silently producing an athlete whose team discount never applies. A seat license is not required, since the discount is for the athlete’s own purchase and not a license entitlement. Set org_id to an empty string to remove the affiliation.

Stacking with partner offers

If your platform also has a partner-level offer (e.g. bundle pricing for your annual subscribers), eligible athletes get both: the percents combine multiplicatively, and the total is hard-capped at 30%. A 20% partner offer combined with a 15% org offer gives 1 - (0.80 × 0.85) = 32%, which the cap reduces to 30%. Checkout applies one combined discount, and Saturday’s subscribe landing page shows the stacked percent, the exact number the athlete will pay, along with which sources contributed. See Freemium Model, Bundle offers for the full discount flow.

Listing organizations

Returns all organizations created by your partner account.

Updating an organization

Finding an organization’s athletes

Athletes reference their organization through the org_id field on the athlete record (POST /v1/athletes and PATCH /v1/athletes/{athlete_id}, see Organization offers above). There is no endpoint that lists an organization’s athletes. To build a team roster view, keep your own athlete-to-org mapping as you assert org_id, or for licensed teams use the seat-subscription license list: GET .../licenses returns exactly the athletes the org covers.