# REST API

Base URL: https://api.staging.levr.ai/v1/
Authentication: Bearer — Portal API key

Reference index: https://docs.staging.levr.ai/rest-api-reference/index.md
OpenAPI specification: https://docs.staging.levr.ai/generated/openapi.json

## Make your first request

Ask a Portal administrator to create an API key for your integration. Save it when it is shown; you cannot retrieve it again.

Read the API root to confirm the owning Portal, selected access targets, and permissions. A source key targets the listed channel slugs; pass the selected slug as `source_channel_id` when creating a business. You do not need permission to list all sources.

Each endpoint names its sufficient permission (or OR alternatives). Scope determines which records that permission can affect. Write includes Read only within the same read-capable permission row. Lead submission is write-only and does not allow reading or updating an existing Business.

Confirm the connection:

```sh
curl --request GET \
  --url 'https://api.staging.levr.ai/v1/' \
  --header "Authorization: Bearer $LEVR_API_KEY"
```

Store the key in a secret manager. Keep it out of browser code, logs, prompts, and source control.

Set `LEVR_API_KEY` in your shell to the saved Portal API key before copying the examples. API keys belong to one environment; a staging key cannot authenticate against production. File-transfer credentials returned by an upload or download operation are separate: use the credential named by that operation.

The [published OpenAPI download](/generated/openapi.json) is public and needs no API key. The API's `/v1/openapi.json` endpoint requires a Portal API key and describes the resources granted to that key. Use the documented resource paths or URLs returned by API reads; a documentation page URL is not an API endpoint.

## Choose your task

Read the resource guide for the work you want to do. Each guide links to the exact operations; you do not need to read the entire reference.

- [Create businesses in the receiving Portal](/guides/): choose a step-by-step guide for a business profile, client intake, deal application, or funding request.
- [Complete client intake](/rest-api-reference/client-intake-applications/): answer questions, attach documents, use Autofill, and submit.
- [Find funding recommendations](/guides/matchmaking/): complete a project's Criteria, calculate matches, and review results.
- [Create and manage deals](/rest-api-reference/deals/): create a Deal for your own Portal or a chosen recipient, then follow its progress.
- [Complete a Deal application](/rest-api-reference/deal-applications/): prepare an application for one recipient and submit it.
- [Receive updates](/rest-api-reference/webhooks/): configure and verify webhooks.

AI agents can start with [the Markdown reference index](/rest-api-reference/index.md), then fetch only the relevant resource and operation Markdown. OpenAPI defines the exact REST paths and schemas. Application questions come from the record's returned `contract_url`.

## Make reliable requests

Follow the headers and inputs on each operation page. Unsupported query parameters are rejected rather than silently ignored.

## Read every page

REST collections return `items`, `next_cursor`, and `previous_cursor`. Set `page_size` using the range documented for that operation. Defaults and limits can differ between collections.

For example, read a page of businesses:

```sh
curl --request GET \
  --url "https://api.staging.levr.ai/v1/businesses/?page_size=5" \
  --header "Authorization: Bearer $LEVR_API_KEY"
```

If `next_cursor` is not null, assign that exact value to `NEXT_CURSOR` and request the same collection with the `cursor` query parameter. Encode it as a query value rather than editing or decoding it:

```sh
curl --get \
  --url "https://api.staging.levr.ai/v1/businesses/" \
  --data-urlencode "page_size=5" \
  --data-urlencode "cursor=$NEXT_CURSOR" \
  --header "Authorization: Bearer $LEVR_API_KEY"
```

Repeat until `next_cursor` is null. Keep the resource, filters, ordering, and page size unchanged while paging. Start a fresh first-page request when those controls change. Cursors are opaque values scoped to their collection; never reuse one for another application or collection. For collections that support backward paging, pass a non-null `previous_cursor` as `cursor` to return to an earlier page. Answers, repeatable answer items, and answer files support forward paging only; their `previous_cursor` is always null.

## Retry safely

For a write requiring `If-Match`, read the resource first and send its complete `ETag`, including quotes. Use the new ETag after each write. A `412 precondition_failed` means the resource changed: read it again and reconcile your change before retrying.

For an operation requiring `Idempotency-Key`, use a new key for a new command. Reuse it only for an identical retry, with the same method, resource, payload, and precondition.

A `429` response includes `Retry-After`; wait at least that long. Other errors include a message and structured details identifying what needs attention. When contacting support, include the response's `Request-Id`, never your API key.
