Skip to main content
The generated endpoint pages are the exact API contract for production integrations. Production requests use https://api.member.dev plus the canonical /api/v1 path prefix. Bare /api routes may still respond for backward compatibility, but new integrations should use /api/v1. Use it for:
  • Exact paths and methods.
  • Path, query, and body parameters.
  • Request and response schemas.
  • Current endpoint tags.
Use the authored guides for:
  • Which endpoints to combine for a workflow.
  • Which credential to use.
  • What product concepts mean.
  • Alpha caveats that are not obvious from OpenAPI alone.

Authentication in the playground

Most endpoints use bearer authentication. Paste one of these into the auth field:
  • A platform access token.
  • A contact access token.
  • A team API key beginning with mio_sk_.
Some public and webhook endpoints do not require a bearer token even though the global docs auth field is shown.

Created resources

A create request that succeeds returns 201 Created. When the new resource has its own GET URL that the creator can follow, the response also carries:
  • A Location header with that URL.
  • The same URL in data.links.self, added when the body had no links.self of its own.
The URL is a path, not a full URL. It is relative to the API origin, uses the same prefix as your request (/api/v1), and is percent-encoded. Request it with the same credentials and you get 200 with the same type and id.
These create requests carry it: Do not assume a 201 always has a Location. These do not:
  • Action requests that return 201, such as warning or banning a member, reacting to a post, or following a member.
  • Nested creates, where the new item has no GET URL at the create URL plus its id, such as adding an item to a playlist, a tag to a contact, or a step to a drip campaign.
  • Creates from a template, and upload or session setup requests such as an upload URL.
  • Comments, access rules, files, admin discussions, and hub events. These creates return 201 as before, with no Location and an unchanged body.
Treat a missing Location as normal. Fall back to the id in the body and the resource’s own GET path from the endpoint reference.
Browsers running on another origin cannot read the Location header, because the API does not expose it through CORS. Read data.links.self from the body instead.

Accepted requests

A 202 Accepted means the API took the request and is still working on it. Three routes tell you where to poll for progress, with a Location header: The import and transcode 202 bodies also set data.links.self to the same path. The domain verify request sends Location only while the domain is still pending. If the domain is already verified, the request answers 200 with no Location. Every other 202 carries no Location, because there is nothing to poll.

Updating with PATCH

On PATCH /api/v1/teams/{team_id}, PATCH /api/v1/users/{user_id} and PATCH /api/v1/roles/{role_id}, only the fields you send change:
  • An omitted field is left unchanged.
  • An explicit null clears a field that can be empty.
  • An explicit null on a field that cannot be empty is a 422, and nothing in the request is written.
The 422 has a source.pointer for the field. Teams accept an envelope body or a flat body, and the pointer follows the shape you sent: /data/attributes/name for an envelope, /name for a flat body. Users and roles take flat bodies, so their pointers look like /is_active and /name.
A few details:
  • The rejection applies when the same request also changes other fields. {"first_name": "Ada", "is_active": null} is a 422 and first_name keeps its old value.
  • Renaming a system role is still a 409. A null name on a system role is a 422, because the body is checked first.
  • An empty body {} changes nothing. Users and roles answer 200. Teams answer 422 with code no_updatable_fields.
The OpenAPI schema for these three request bodies still shows is_active and both name fields as nullable. That is a known gap in the published schema. The 422 is the real behavior, so do not rely on a generated client to stop you from sending null.
Before this change, null was dropped on all three endpoints. PATCH /api/v1/users/{user_id} with {"first_name": null} answered 200 and changed nothing. See the breaking changes log for the full old and new behavior.