Skip to content
Levr API Documentation
Download OpenAPI specOpenAPI

Hand off to an AI agent

Copy instructions to your AI agent

Copy this guide into your AI agent. It links to the current REST API and MCP documentation.

You are helping someone integrate their system with Levr. Use Levr's published documentation and machine-readable contracts as the source of truth. Do not invent endpoints, fields, or MCP tools.

  1. Start with the Levr API documentation to choose between a server-to-server REST integration and a user-authorized MCP connection.
  2. For REST, read the Markdown REST API guide, choose the user’s task, then fetch only the relevant resource guide and operation Markdown. Resource indexes include task guidance. For funding recommendations, start with the Matchmaking guide. Use the OpenAPI specification for exact paths, authentication, parameters, and envelope schemas.
  3. For REST client intake, Deal applications, or project Criteria, fetch that resource's contract_url. Its Application Contract is the authority for the current questions, stable keys, repeatable groups, file-transfer steps, accepted answer shapes, conditional visibility, supported operation URLs, and integration instructions. Repeatable fields require the returned item_id. File bytes use the expiring upload_url and multipart field named file; they never belong in JSON. Do not substitute a static example or the latest application definition.
  4. For an AI client acting with a signed-in user's access, read the MCP connection instructions in Markdown first, then the Model Context Protocol guide if needed. Let the connected MCP server expose its current tools and input contracts; do not infer tools from the REST API. Read the relevant MCP resource guide and follow the discovered tool’s revision, file-transfer, and confirmation requirements.
  5. Use URLs from the record handoff when supplied; otherwise use this documentation environment. Keep API keys and file-transfer credentials out of browser code, logs, prompts, and source control.
  6. Before implementing a write, verify authentication, required inputs, idempotency, error responses, and retry guidance in the current contract. If an operation is not documented, do not assume it exists.

Early access

Request an integration

Tell us what your integration needs to do. Add an email if you want a reply.

Projects

Matchmaking

Find funding partners that may fit a business’s funding goal.

Read as Markdown

REST operations · MCP tools

Complete a Project's Criteria, calculate funding recommendations, and create a Deal for a chosen recipient. Start with an existing Project; to create a business and its client-visible funding request first, follow Find funding matches.

A Project can stay private to your Portal; client matchmaking access is not required for that workflow. If you add a client funding request, it shares the Project's Criteria and matching work. Matching produces recommendations; creating and submitting a Deal are later steps.

Before you start

Use a server-side API key with access to this Project and projects:read, project_criteria:write, and project_matching:write. Creating a Deal additionally needs deals:write. The Deal guide explains how to complete and submit the application with deal_applications:write.

The receiving Portal must have matchmaking enabled and published recipient Criteria available to compare against. If the project has a linked client funding request, the business must still have an active relationship with your Portal.

Every request includes Authorization: Bearer <API_KEY>. JSON writes use Content-Type: application/json. Give each mutation its own Idempotency-Key and retain the key and body for retries. Examples use illustrative IDs and abbreviated responses. Replace them with the IDs and URLs your API returns; Get started provides the API origin.

1. Read the questions and current answers

Read the Project to get its business ID and application links:

GET /v1/projects/proj_example/

Response · selected fields

{
  "id": "proj_example",
  "business": { "id": "biz_example" },
  "contract_url": "https://YOUR_API_HOST/v1/projects/proj_example/matchmaking-application/contract/",
  "answers_url": "https://YOUR_API_HOST/v1/projects/proj_example/matchmaking-application/answers/"
}

Save business.id for Deal creation, then follow the two application URLs:

GET /v1/projects/proj_example/matchmaking-application/contract/
GET /v1/projects/proj_example/matchmaking-application/answers/

The contract describes each question's exact block_key, field_key, value type, and available operations. A question might look like this within the returned questions array:

{
  "label": "Requested funding",
  "block_key": "<amount-block-key>",
  "fields": [
    {
      "field_key": "<amount-field-key>",
      "value_schema": { "type": "string" }
    }
  ]
}

These keys illustrate the structure; they are not universal field names. Use your contract's keys and constraints. Complete the relevant business and funding information, including conditional questions and repeated entries.

Save the answers response's ETag header for the next write. Its answers_revision identifies the version you reviewed. Answers are paginated: follow next_cursor until it is null when reviewing the full application.

2. Save or edit Criteria

Send only the values you want to change. This example assumes the contract accepts the amount as a string.

PATCH /v1/projects/proj_example/matchmaking-application/answers/
If-Match: <ETag from the answers GET>
Idempotency-Key: equipment-criteria-1
{
  "updates": [
    {
      "block_key": "<amount-block-key>",
      "field_key": "<amount-field-key>",
      "value": "250000"
    }
  ]
}

Response · 200, selected fields

{
  "answers_revision": 2,
  "updated_answers": [
    {
      "block_key": "<amount-block-key>",
      "field_key": "<amount-field-key>",
      "value": "250000"
    }
  ]
}

The response confirms the saved values and includes the new ETag. Use it for your next edit; you do not need another read just to confirm the write. To correct the amount later, send the corrected value with the latest ETag and a new key. On 412, read and reconcile concurrent edits before sending another update.

For rows such as owners or assets, use the contract's repeatable_items_url and retain each returned item_id. A row's position is not its identity.

3. Attach supporting documents

Choose a file question from the contract. Request an upload using operations.file_uploads_url:

POST <operations.file_uploads_url>
{
  "block_key": "<financial-statements-block-key>"
}

For a file inside a repeated row, also send its item_id.

Response · selected fields

{
  "id": "upl_example",
  "upload_url": "https://YOUR_API_HOST/v1/projects/proj_example/matchmaking-application/answers/files/upl_example/",
  "multipart_field": "file",
  "max_size_bytes": 26214400
}

Follow the returned URL and size limit; do not construct the URL from this example. The upload URL expires at the response's expires_at. Upload the file bytes as multipart, with the latest answers ETag:

curl -X POST "$UPLOAD_URL" \
  -H "Authorization: Bearer $LEVR_API_KEY" \
  -H "If-Match: $ANSWERS_ETAG" \
  -H "Idempotency-Key: equipment-statements-1" \
  -F "file=@financial-statements.pdf"

Let your HTTP client set the multipart boundary. A successful upload returns the attached file, the new answers_revision, and its ETag. Keep that revision for matching. Use operations.files_url when you need to list attachments; file bytes do not go in the answer JSON.

If the upload response is lost, retry the same URL with the same key, filename, bytes, and original If-Match. Requesting a new upload URL starts a separate transfer and can attach a duplicate. If an unused URL expires, request a new one.

4. Start matching

Review the saved Criteria, then send their current answers_revision:

POST /v1/projects/proj_example/matchmaking-runs/
Idempotency-Key: equipment-matching-1
{
  "expected_answers_revision": 3
}

Response · 202, selected fields

{
  "id": "pmrun_example",
  "status": "queued",
  "answers_revision": 3,
  "url": "https://YOUR_API_HOST/v1/project-matchmaking-runs/pmrun_example/",
  "results_url": "https://YOUR_API_HOST/v1/project-matchmaking-runs/pmrun_example/results/"
}

Save the run ID and URLs before continuing. Retry a lost response with the same key and body to recover the same run. A Project can have only one active calculation; do not start another while your saved run is in progress.

5. Wait for results

Poll the returned url while the status is queued or running. Space requests apart and respect rate-limit responses.

GET /v1/project-matchmaking-runs/pmrun_example/

Response · selected fields

{
  "id": "pmrun_example",
  "status": "completed",
  "is_stale": false,
  "impactful_missing_fields": [],
  "results_url": "https://YOUR_API_HOST/v1/project-matchmaking-runs/pmrun_example/results/"
}

Alternatively, configure a Webhook Destination for project_matchmaking_run.status_changed before starting the run. Follow Webhook setup and signature verification. This event reports settled statuses: completed, partially_complete, failed, or cancelled. It does not report every progress update.

Webhook · selected fields

{
  "type": "project_matchmaking_run.status_changed",
  "data": {
    "object": {
      "id": "pmrun_example",
      "project": "proj_example",
      "status": "completed"
    }
  }
}

Verify the signature, deduplicate by the event ID, and fetch the run for its current state. Keep polling as a recovery path. For partially_complete, review the available results and unresolved failures before using them. A failed or cancelled run is not a completed assessment.

Stop or resume a calculation

To stop an active calculation, POST to /v1/project-matchmaking-runs/{run_id}/cancel/ with a new Idempotency-Key and an empty JSON body ({}). Poll the run to confirm its status. Cancellation preserves any results that have already completed.

To resume unresolved work on a failed or cancelled run, POST to /v1/project-matchmaking-runs/{run_id}/retry/ with {} and a new Idempotency-Key. The response is 202; keep polling the same run. Retry uses that run's original Criteria and recipient snapshot. If you changed the Criteria, start a new calculation after the old one settles instead.

A second calculation while one is active is rejected. A shortlist write is also rejected if the recipient's package version differs from the version you reviewed. Read the current run or results and review the change before trying again.

Use webhooks or REST polling for integration updates. The Portal handles its own websocket connection.

6. Review recommendations

Fetch results_url. When next_cursor is non-null, pass its value as the next request's cursor query parameter, preserving the same filters and page size. Continue until it is null.

GET /v1/project-matchmaking-runs/pmrun_example/results/

Response · selected fields

{
  "items": [
    {
      "id": "pmres_example",
      "recipient": { "id": "northstar-finance", "label": "Northstar Finance" },
      "classification": "match",
      "package_version": 2,
      "availability": "available",
      "is_selected": false
    }
  ],
  "next_cursor": null
}

Review each result's evaluation and availability, including missing information and uncertainty. Classifications include match, partial_fit, insufficient_information, not_a_match, and not_assessed. An empty list does not establish a suitable match. If the run is stale, review the changed Criteria and start a new run after the current run settles.

7. Save a shortlist

Read the selections for this run and save that response's ETag. Selections have their own revision; do not reuse the answers ETag.

GET /v1/projects/proj_example/matchmaking-selections/?run_id=pmrun_example

Then add the reviewed result, using its id and package_version:

PATCH /v1/projects/proj_example/matchmaking-selections/
If-Match: <ETag from the selections GET>
Idempotency-Key: equipment-shortlist-1
{
  "run_id": "pmrun_example",
  "additions": [
    {
      "match_result_id": "pmres_example",
      "expected_package_version": 2
    }
  ]
}

The response contains the updated selections and revision. Saving a selection records a shortlist choice; it does not create a Deal. This step is optional if your integration goes straight from a reviewed result to Deal creation.

8. Create and submit a Deal

For a chosen, available recipient, pass the result's recipient.id to Deal creation. The match result ID used for selections is a different identifier.

POST /v1/deals/
Idempotency-Key: equipment-northstar-deal-1
{
  "business_id": "biz_example",
  "project_id": "proj_example",
  "recipient_id": "northstar-finance"
}

Create one Deal per intended recipient and save each response. Then follow Complete and submit a Deal to read its application, fill any remaining answers, upload required documents, check readiness, and submit. A match does not establish approval or funding.

In the Portal, open the Project to review Criteria, results, and selections; open the created Deal for its application and submission state. For MCP integrations, use the Matchmaking tools and discover their live contracts rather than translating REST paths into tool names.