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.

REST API reference

Webhooks

Receive signed events when something changes in Levr.

DeliveryAt least once
OrderingNot guaranteed
Maximum attempts8
Request timeout10s

Configure a destination

Ask a Portal administrator to add a destination in API settings → Webhooks. Enter a label, a public HTTPS receiver URL and the selected events.

Save the signing_secret shown at creation in your secret manager. It is the complete whsec_... string, not an API key or a base64-decoded value. Share it separately from the destination's copied implementation instructions. Existing destinations do not reveal the plaintext again.

Use the destination's Copy instructions, Send test event and Rotate secret controls to implement, test and rotate the receiver. Rotation reveals a new secret and the previous secret's expiry. The configured overlap defaults to 24 hours; use the returned expiry rather than assuming the default. During overlap Levr sends signatures for both secrets.

Choose events

Subscribe each destination only to the resource changes its integration needs. An event is created after the change commits in Levr, then delivered independently to every active destination that selected it.

business.createdAfter Levr saves the Business in your Portal.business.status_changedAfter Levr commits a change to the business's stage in this provider's business pipeline.business.updatedAfter Levr saves a change to the Business name or referral information in your Portal.client_intake_application_autofill_run.settledAfter Levr commits the terminal outcome of an asynchronous autofill Run.client_intake_application.createdAfter Levr commits the shared Client Intake Application.client_intake_application.status_changedAfter Levr commits a Client Intake Application status transition, including submission.client_intake_application.submittedAfter Levr commits a successful Client Intake Application submission.client_intake_application.updatedAfter Levr saves a change to the Client Intake Application answers.deal_application_autofill_run.settledAfter Levr commits the terminal outcome of an asynchronous autofill Run.deal_application.createdAfter Levr grants your Portal access to the Deal Application.deal_application.status_changedAfter Levr commits one Deal Application status transition.deal_application.submittedAfter Levr commits the shared Deal Application submission.deal_application.updatedAfter Levr saves a change to the Deal Application answers.deal.createdAfter Levr saves the new Deal.deal.stage_changedAfter Levr saves the Deal's new pipeline stage.deal.updatedAfter Levr commits a Deal edit, Project association, or shared application lifecycle change.project.createdAfter Levr saves the new Project.project_matchmaking_application_autofill_run.settledAfter Levr commits the terminal outcome of an asynchronous autofill Run.project_matchmaking_run.status_changedAfter a calculation settles as partially complete, completed, failed, or cancelled.project.stage_changedAfter Levr commits one Project stage transition.project.updatedAfter Levr saves a change to the Project or its Criteria answers.

Implement the receiver

  1. Accept the raw request body. Do not parse or modify it before signature verification.
  2. Verify the signature. Compare Levr-Signature against the unmodified body and reject stale timestamps.
  3. Return a successful response quickly. Queue longer work after acknowledging the event.
  4. Make processing idempotent. Delivery is at least once, so the same event can arrive more than once.

Request headers

HeaderUse
Levr-SignatureVerify that the request came from Levr.
Levr-Event-IDIdentify the immutable event across destinations.
Levr-Delivery-IDIdentify this destination's delivery across retry attempts.
Content-TypeWebhook requests use application/json.

Accept signatures generated within 300 seconds of the current time.

Verify the signature

The header is comma-separated: t=UNIX_SECONDS,v1=LOWERCASE_HEX. Rotation can add another v1. Compute HMAC-SHA256 with the complete secret's UTF-8 bytes over the canonical decimal ASCII timestamp, one literal period and the unmodified request-body bytes. Compare the lowercase hexadecimal digest using a constant-time comparison. Accept if any configured secret matches any v1 and the timestamp is within 300 seconds in either direction.

Python
import hashlib
import hmac
import time

def verify_levr(raw_body, header, secrets, now=None):
    parts = [part.split("=", 1) for part in header.split(",") if "=" in part]
    timestamps = [value for name, value in parts if name == "t"]
    signatures = [value for name, value in parts if name == "v1"]
    try:
        timestamp = int(timestamps[0])
    except (IndexError, ValueError):
        return False
    current = int(time.time()) if now is None else now
    if abs(current - timestamp) > 300 or not signatures:
        return False
    signed = str(timestamp).encode("ascii") + b"." + raw_body
    return any(
        hmac.compare_digest(
            hmac.new(secret.encode("utf-8"), signed, hashlib.sha256).hexdigest(), signature
        )
        for secret in secrets for signature in signatures
    )

Read bytes before JSON parsing; do not reconstruct JSON for verification. Levr emits one canonical integer timestamp. The current verifier uses the first t, parses it as an integer and signs its canonical decimal representation; it ignores unrecognized or malformed comma fragments. Reject a missing/unparseable timestamp, a missing or mismatched signature, and timestamps outside the tolerance. Receivers may reject duplicate timestamps and noncanonical header syntax more strictly. Check Levr-Event-ID against the verified body's id and deduplicate by that immutable event ID. Levr-Delivery-ID identifies one destination delivery and stays stable across retries.

Delivery and recovery

Return any 2xx response only after durable acceptance, within 10 seconds. Timeouts, connection failures and non-2xx responses retry, up to 8 total attempts. The scheduled delays are 60, 120, 240, 480, 960, 1920 and 3600 seconds; worker availability can delay actual arrival. Redirects are not followed.

Events can arrive out of order. Use the verified event as a signal, then read the current REST resource before updating your system. Inspect failed deliveries and attempts in your Portal. If retries end before your receiver accepts an event, fix the receiver and read the affected records through REST to bring your system up to date.

Use a Portal test event to check your receiver's signature verification and delivery handling. It follows the same delivery path and sets test_mode: true, without changing a Business, Project or Deal. Exclude test events from production record updates, then check a real resource change to verify your complete integration.