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

# Authentication

> OAuth 2.1 with PKCE at the Mogul issuer, the 14 scopes, the two sides, the roles, and the token every request carries.

<Note>
  The Marketplace API is in a private beta. It answers only for accounts Investorlift has enabled. [Access](/marketplace/access) says how to ask for one. A route shape on these pages can change before the beta ends. The changelog records every change.
</Note>

The Marketplace API takes one credential: an OAuth 2.1 access token that a seller or a buyer grants your application on
Mogul. No static key exists. Every request carries the token in the `Authorization` header as `Bearer`. The token names
the person, your application and the scopes. The API reads the permission of that person from its database on every
request. The God Mode API is different: it takes a `zpka_` key ([Authentication](/guides/concepts/authentication)), and
a key never opens a marketplace route.

## The issuer

The issuer is `https://mogul.investorlift.com/api/auth`. Read its endpoints from the discovery document. Do not type
them.

| What                                  | Where, under the issuer             |
| ------------------------------------- | ----------------------------------- |
| The discovery document                | `/.well-known/openid-configuration` |
| Dynamic client registration           | `/oauth2/register`                  |
| Revocation                            | `/oauth2/revoke`                    |
| The authorization and token endpoints | Named in the discovery document     |

## The flow

<Steps>
  <Step title="Register a client">
    Register your application once at `/oauth2/register`, or ask Investorlift for a registered app ([Access](/marketplace/access)).
    A dynamically registered client is personal. It holds consent from at most one organization and three users. The fourth
    consent answers `client_limit` on the consent page. A registered app connects many organizations. It shows its name and a
    verified badge on the consent page.
  </Step>

  <Step title="Send the person to the authorization endpoint">
    Use the authorization code grant with PKCE, method `S256`. Ask for the scopes you need and for `offline_access`. The
    consent page prints one sentence per scope and the name of your application. A dynamically registered client shows as
    "Unregistered application" with its redirect host.

    The page also carries the Marketplace API Terms checkbox. A seller accepts the terms once for the organization. A buyer
    accepts them once as a person.
  </Step>

  <Step title="Exchange the code for tokens">
    Send the code, the PKCE verifier and `resource=https://api.investorlift.com/marketplace/v1` to the token endpoint. The
    `resource` value puts the API in the audience of the access token. Without it, the token has no marketplace audience,
    and the gateway answers `401 unauthorized`. The answer carries an access token and a refresh token.
  </Step>

  <Step title="Call the API">
    Send `Authorization: Bearer <token>` on every request. Start with `GET /me`, which says what the token can do.
  </Step>

  <Step title="Refresh">
    A marketplace access token lives 15 minutes. Use the refresh token to get a new pair before it expires. Refresh tokens
    rotate: every refresh answers a new refresh token, and the old one stops. A refresh token lives 30 days.
  </Step>
</Steps>

## Revoke a token

Send the refresh token to `/oauth2/revoke` under the issuer. The revocation ends the refresh token and every access
token it minted. A person can also remove your application in their account settings on Mogul. The old access token then
answers `401 unauthorized` within 15 minutes, and a refresh fails at once.

## The 14 scopes

Read, write and manage are separate grants. A CRM that only reads events never holds a write scope. Ask for the
smallest set that does the job. The consent page prints the sentence in the second column.

| Scope                 | What it grants                                                                 | Side | Role                            |
| --------------------- | ------------------------------------------------------------------------------ | ---- | ------------------------------- |
| `marketplace:profile` | Read your account, your organization and your trust tier.                      | both | any                             |
| `deals:read`          | Read your deals as a seller, and the deals you see as a buyer.                 | both | any                             |
| `deals:write`         | Create drafts, add media and documents, publish deals and change their status. | sell | member                          |
| `offers:read`         | Read the offers on your deals as a seller, and your own offers as a buyer.     | both | any                             |
| `offers:write`        | Make, counter, accept, decline and withdraw offers.                            | both | member                          |
| `inquiries:read`      | Read the inquiries and address requests on your deals, and your own.           | both | any                             |
| `inquiries:write`     | Send inquiries and address requests, and answer address requests.              | both | member                          |
| `leads:read`          | Read the leads on your deals with their history.                               | sell | any                             |
| `leads:write`         | Set a lead status, add a lead and file a strike.                               | sell | member                          |
| `contacts:read`       | Read the email address and the phone number of a buyer on your deals.          | sell | owner or admin                  |
| `reviews:read`        | Read a seller public profile and the reviews of that seller.                   | both | any                             |
| `buy_boxes:manage`    | Read and change your buy boxes and their alerts.                               | buy  | any                             |
| `webhooks:manage`     | Create, read and delete the webhook endpoints of your side.                    | both | owner or admin on the sell side |
| `events:read`         | Read the event feed of your side.                                              | both | any                             |

`marketplace:profile` opens `GET /me`, which both sides call. A token without the scope of an operation answers
`403 insufficient_scope`, and the body names the scope in `scope`. The three proof of funds routes under
`/buy/me/proof-of-funds` are under `offers:write`.

## The two sides and `GET /me`

Every route lives under one side. A `/sell/` route acts for your own organization, limited by your role. A `/buy/` route
acts for you as a buyer. One token can hold both sides. `GET /me` is the one route outside both. Call it first: it
answers what the token can do now.

| Refusal                    | When                                                                                                                                                                                                                                                               |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `403 no_organization`      | A `/sell/` call from an account with no organization of its own.                                                                                                                                                                                                   |
| `403 designation_required` | A `/sell/` call for an organization that does not sell on Mogul, or a `/buy/` call from an account that does not buy.                                                                                                                                              |
| `403 terms_required`       | The side did not accept the Marketplace API Terms yet. Accept them on the consent page, then start a new authorization. The body names the terms in `agreement_id`. `GET /me` answers before a side accepts the terms, and every other route can answer this code. |
| `403 insufficient_scope`   | The token lacks the scope of the operation. The body names the scope.                                                                                                                                                                                              |
| `403 insufficient_role`    | A member's token calls a seller-side webhook route. Only an owner or an admin can.                                                                                                                                                                                 |

`GET /me` answers one object in `data`:

| Field          | What it carries                                                                                                                        |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `user`         | Your buyer id (`byr_`) or null, your name and email address, and the email and phone verification flags.                               |
| `organization` | Your own organization: the seller id (`slr_`), the name, the slug, your role, and its designations. Null when you have none.           |
| `designations` | The designations of you and of your organization.                                                                                      |
| `sides`        | The sides this account reaches today: `sell`, `buy`, or both.                                                                          |
| `scopes`       | The scopes this token carries.                                                                                                         |
| `client_id`    | The OAuth client that holds the token, or null.                                                                                        |
| `trust`        | The tier, each fact with its source, and the next step to the tier above ([Trust and limits](/marketplace/concepts/trust-and-limits)). |
| `caps`         | One row per cap: `action`, `limit`, `used`, `remaining` and `resets_at`.                                                               |
| `terms`        | For each side, `accepted` and the `agreement_id`.                                                                                      |
| `environment`  | `production` on the live host, `sandbox` elsewhere.                                                                                    |
| `api_version`  | The contract version, the same value as `meta.api_version` on every response.                                                          |

## Roles

An organization has owners, admins and members. Every write scope acts for any member. Two scopes reach personal data
and delivery endpoints: `contacts:read` and `webhooks:manage`. The role gate sits on the operation, not on the token.

A member's token on a seller-side webhook route answers `403 insufficient_role`. The body names the roles that run the
operation in `required_roles`, and your role in `role`. The six seller-side webhook operations carry the gate, and no
other operation does. The API serves a buyer's email, phone and phone type only when the token holds `contacts:read`
and the member is an owner or an admin. Otherwise those fields are absent, and the rest of the response is normal.

The API reads the role from the membership on every request, never from the token. When a membership ends, the token
stops for that organization on its next request.

## What the gateway checks and what the origin loads

The gateway at `api.investorlift.com` verifies the access token against the keys of the issuer: the signature, `iss`,
`exp` and `aud`. It then forwards the request to the origin with the identity from the token. The origin reads the
person from `X-On-Behalf-Of` as `user:<sub>`, your client id, the scopes and the request id from headers the gateway
sets. The gateway deletes your token before the request leaves it, and it drops any of these headers you send. You
never send them.

A claim is identity, never permission. On every request the origin loads the user, the own organization, the role, the
designations and the standing from its database. So a ban, a role change or a stop takes effect on the next request,
inside the 15 minutes of the token. A suspended or deleted account answers `401 unauthorized`. So does an account with
no verified email address. A stopped client, user or organization answers `403 forbidden`.

## Call `GET /me`

The first call of every integration. Put the access token in the environment variable `MARKETPLACE_TOKEN`.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.investorlift.com/marketplace/v1/me" \
    -H "Authorization: Bearer $MARKETPLACE_TOKEN"
  ```

  ```javascript Node.js theme={null}
  const res = await fetch("https://api.investorlift.com/marketplace/v1/me", {
    headers: { Authorization: `Bearer ${process.env.MARKETPLACE_TOKEN}` },
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  const { data, meta } = await res.json();
  console.log(data.sides, data.trust.tier, meta.request_id);
  ```

  ```python Python theme={null}
  import os

  import requests

  r = requests.get(
      "https://api.investorlift.com/marketplace/v1/me",
      headers={"Authorization": f"Bearer {os.environ['MARKETPLACE_TOKEN']}"},
      timeout=30,
  )
  r.raise_for_status()
  body = r.json()
  print(body["data"]["sides"], body["data"]["trust"]["tier"], body["meta"]["request_id"])
  ```
</CodeGroup>

Next: [Identifiers and the envelope](/marketplace/concepts/identifiers-and-envelope),
[Errors](/marketplace/concepts/errors) and [Trust and limits](/marketplace/concepts/trust-and-limits). The
[seller quickstart](/marketplace/quickstart-seller) and the [buyer quickstart](/marketplace/quickstart-buyer) run the
flow end to end.


## Related topics

- [Authentication](/guides/concepts/authentication.md)
- [Frequently asked questions](/guides/faq.md)
- [API reference](/api-reference/introduction.md)
- [Quickstart for sellers](/marketplace/quickstart-seller.md)
- [The Investor object](/api-reference/objects/investor.md)
