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

# Partner API

> Build company-scoped partner integrations with OAuth or API keys.

# Partner API

The Partner API gives partner users a company-scoped way to work with the
Journeybee data shared with them. The partner surface is separate from the
admin API and follows the same room, partnership, and sharing settings as the
partner portal.

## Base URL

```
https://api.journeybee.io/v1
```

## Authentication

Partner connections use either OAuth or a partner API key. Send the credential
in the `Authorization` header:

```text theme={null}
Authorization: Bearer <access-token-or-api-key>
```

OAuth (authorization-code + PKCE) is how interactive MCP clients — Claude,
ChatGPT, Cursor, and similar — connect to your partnership data. Discovery and
client registration happen automatically via the MCP server, so there's
nothing to configure by hand; see [Partner MCP](/guides/partner-mcp) for the
connect flow. For custom REST integrations, use a partner API key instead.

Partner API keys are issued in the partner portal and are shown only once.
Store them securely and send them as bearer credentials.

## Getting started

Call `GET /v1/partner/me` with your credential to find out who you are and
which partnerships you can act on:

```bash theme={null}
curl https://api.journeybee.io/v1/partner/me \
  -H "Authorization: Bearer YOUR_CREDENTIAL"
```

The response includes your user identity, your read/write permissions, and
the partnerships available to you — each with a `uuid`, `name`,
`partner_type`, and `status`. That `uuid` is the `{partnershipId}` you send on
every other request (see [Company and partnership scope](#company-and-partnership-scope)
below).

## Examples

List deals for a partnership:

```bash theme={null}
curl https://api.journeybee.io/v1/partner/{partnershipId}/deals \
  -H "Authorization: Bearer YOUR_CREDENTIAL"
```

Create a lead:

```bash theme={null}
curl -X POST https://api.journeybee.io/v1/partner/{partnershipId}/leads \
  -H "Authorization: Bearer YOUR_CREDENTIAL" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com"
  }'
```

## API keys

Partner API keys are created and revoked on the portal's **API & MCP** page.
When you create one you choose **read** and/or **write** access — the same
scopes an OAuth connection carries — and the full key is shown exactly once,
so store it securely. A key is scoped to your partner user and the company
whose portal you created it on (not to a single partnership), and starts with
the `jb_partner_` prefix. Each partner user may have up to 10 active keys per
company — revoke ones you no longer need before creating more.

## Scopes and permissions

Connections can have `read` and `write` access. Most partner operations are
read-only; write endpoints require the connection to have write access.
Grant only the permissions an integration needs.

## Company and partnership scope

Credentials are scoped to a partner user and company. A partner can have
connections for multiple companies, and each company must be authorized
separately.

The partnership is selected for each API request:

```text theme={null}
/v1/partner/{partnershipId}/leads
/v1/partner/{partnershipId}/deals
```

The API validates that the authenticated partner is an active member of the
requested partnership at the credential's company. A credential never grants
access to partnerships at another company.

## IDs are UUIDs

Every id in a partner API request or response is a UUID — partnership, lead,
deal, tag, user, and contact ids are all `uuid` strings. IDs you receive back
from a request round-trip directly into filters and update calls; the API
never exposes numeric ids as resource identifiers. A few numeric fields do
appear as display-only metadata (logo/asset ids, custom-field option ids
inside `options`) — these are never accepted as identifiers in a request.

## Responses & errors

List endpoints return a paginated envelope:

```json theme={null}
{
  "data": [],
  "pagination": { "page": 1, "per_page": 25, "total": 42, "total_pages": 2 }
}
```

Errors follow a single envelope:

```json theme={null}
{
  "error": { "code": "not_found", "message": "Lead not found" }
}
```

`code` is one of `unauthorized`, `forbidden`, `module_disabled`, `not_found`,
`validation_error`, `conflict`, `rate_limit_exceeded`, or `internal_error`.
`module_disabled` means the company hasn't enabled the Partner API for its
portal.

Requests are rate-limited to **500 requests per minute** per partner user —
each partner user has their own budget, separate from other users at the same
company. Exceeding it returns a `429 Too Many Requests` response with a
`Retry-After` header.

## Field requirements

Custom fields on leads and deals can be marked required, or controlled by a
custom field rule (auto-populating, hiding, or locking another field). Before
creating or updating a lead or deal, call the matching requirements endpoint
to learn the constraints your submission must satisfy:

```
GET /v1/partner/{partnershipId}/leads/requirements
GET /v1/partner/{partnershipId}/deals/requirements
```

The response lists the custom fields available to this partnership — with
each field's `required` flag — and the active rules that apply to them:

```json theme={null}
{
  "fields": [
    {
      "id": "b3f1c2a0-1111-4a2b-9c3d-000000000001",
      "label": "Deal Type",
      "type": "select",
      "required": false,
      "options": [{ "id": 10, "label": "Enterprise" }]
    },
    {
      "id": "b3f1c2a0-2222-4a2b-9c3d-000000000002",
      "label": "Renewal Terms",
      "type": "text",
      "required": true,
      "options": null
    }
  ],
  "rules": [
    {
      "id": "b3f1c2a0-3333-4a2b-9c3d-000000000003",
      "label": "Show renewal terms for Enterprise",
      "action_type": "show_field",
      "source_field": "b3f1c2a0-1111-4a2b-9c3d-000000000001",
      "source_values": [10],
      "target_field": "b3f1c2a0-2222-4a2b-9c3d-000000000002",
      "target_value": null,
      "value_mappings": null,
      "locked": false
    }
  ]
}
```

<Note>
  `required` applies only while a field is visible — a required field hidden
  by one of the listed rules must **not** be supplied (submitting it returns
  `hidden_by_rule`); it becomes required once its rule condition makes it
  visible. In the example above, "Renewal Terms" is required, but only while
  the "Show renewal terms for Enterprise" rule keeps it visible.
</Note>

Deal field requirements follow the deal's owning partnership; when creating a
deal from another partnership's lead (a distributor roll-up), the lead's own
partnership type governs instead.

Only fields and rules you're actually allowed to read/write on this surface
are included — a rule whose source or target field isn't visible to a partner
is left out entirely, since it can never be satisfied. Both endpoints require
the same room access (`leads`/`deals`) as the corresponding list/create
endpoints.

If a create or update call violates one of these constraints, it returns
`400 validation_error` with a `details` array — one entry per rejected field,
each with the field's `id` (uuid), a machine-readable `reason` (e.g.
`missing_required`, `hidden_by_rule`, `locked_by_rule`), and a human-readable
`message`. See [Custom field validation](/guides/errors#custom-field-validation)
for the full reason code reference.

## Visibility

Partner API responses follow the same visibility rules as the partner portal.
Room settings, partnership settings, sharing settings, campaign sharing, and
ownership rules can affect which records are visible or writable.

The leads and deals endpoints specifically require the company to expose the
matching room (`leads` or `deals`) to that partnership in the partner
portal — the same category, tier, stage, contact-tag, and visibility rules
that gate the room there. If a partnership has no accessible room of that
type, its leads or deals endpoints return `403 forbidden` with
`"The Leads area is not available in your partner portal. Ask the vendor to enable it."`
or
`"The Deals area is not available in your partner portal. Ask the vendor to enable it."`.
Ask the vendor to enable the relevant area in the partner portal. Deal creation
can additionally be disabled independently of read/write access, via the deals
room's settings — in that case `POST /v1/partner/{partnershipId}/deals`
returns `403 forbidden` with
`"Deal creation is disabled in your partner portal. Ask the vendor to enable deal creation."`,
while reading and updating existing deals is unaffected.

## Reference

Every partner endpoint — full request and response schemas — is documented in
the **Partner API Reference** section of these docs, generated from the same
spec this guide describes.
