---
title: "Add Member"
method: POST
path: "/api/v1/org/members"
tags: ["Organization"]
---

# Add Member

`POST /api/v1/org/members`

## Request

- Base URL: `http://localhost:3009`
- URL: `http://localhost:3009/api/v1/org/members`
- Auth: HTTP bearer

Invites a person to your organization. They receive an email invitation and hold no access until they accept, so the roster is unchanged until then.

**Check `data.email_sent`.** The invitation is recorded whether or not the email goes out. When it is `false` the invitee was never told, and re-inviting is refused with `ALREADY_INVITED` — revoke it with Remove Member and invite again.

Requires the `members:write` scope, which only an org admin's API key can carry.

Refusals carry a `code`:

| `code` | Status | Meaning |
|--------|--------|---------|
| `ALREADY_MEMBER` | 409 | That email is already on the roster |
| `ALREADY_INVITED` | 409 | That email already has a pending invitation |
| `MEMBER_LIMIT_REACHED` | 403 | Your plan's seat limit is full — pending invitations reserve a seat |
| `NOT_ORG_LEAD` | 403 | The key's creator is no longer an org admin |

## Request body

- OrgMemberInviteBody: Body for Add Member. The person is invited by email and joins when they accept.
  - `email` string, required: Email address to invite. Matched case-insensitively against the existing roster.
  - `role` 'admin' | 'member', required: Role the invitation carries. `admin` can manage members and billing, `member` can build and run workflows. The narrow third role (`user`) is not invitable over the API yet.

## Response `201`

Created — the invitation is recorded and the invitee has been emailed

- object: Created — the invitation is recorded and the invitee has been emailed
  - `status` integer
  - `message` string
  - `data` OrgMemberInvite: A pending invitation. The invitee holds no access until they accept.
    - `email` string, required: The invited email address, lowercased.
    - `role` 'admin' | 'member' | 'user', required: Role the invitee receives on acceptance.
    - `status` 'pending', required: Always `pending` — acceptance happens in the Floqer app or at signup.
    - `email_sent` boolean, required: Whether the invitation email was accepted for delivery. `false` means the invitation is recorded and holds a seat but nobody was told — re-inviting returns `ALREADY_INVITED`, so revoke it with Remove Member and invite again.

## Other responses

- `401`: Unauthorized — missing or invalid API key
- `403`: Forbidden — not an org admin, or the plan's seat limit is full
- `409`: Conflict — already a member, or already invited
- `429`: Too Many Requests — rate limit exceeded. Check `Retry-After` header for seconds until the limit resets.

---

[API](https://skmtc.dev/floqer/apis/floqer-public-api.md) - [All operations](https://skmtc.dev/floqer/apis/floqer-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/floqer/apis/floqer-public-api/revisions/fce50dc07b20?raw)
