---
title: "Create a referral"
method: POST
path: "/leads"
tags: ["Leads"]
---

# Create a referral

`POST /leads`

## Request

- Base URL: `https://api.lassotech.com/api/v1/rest`
- URL: `https://api.lassotech.com/api/v1/rest/leads`
- Auth: API key in header `x-lasso-access-token`

Create a referral (lead) for an existing partner.

### Identifying the partner
Supply exactly one of `partner_lasso_key`, `partner_slug`, `partner_id`, `partner_name`, or the
`partner_external_system_type` + `partner_external_object_type` + `partner_external_identifier`
triple.

`partner_lasso_key` is the **Lasso Partner Key** (`P-A1B2C3`). It is generated when the partner
is created and can never change, so it is the right value to store on your own partner records.
Slugs are editable and names are not unique.

### Identifying the referred prospect
`email` is required, and so is a name: `contact_name`, `company_name`, or both.

### Linking to your CRM
Passing a CRM deal, opportunity or lead ID (`hubspot_deal_id`, `salesforce_opportunity_id`,
`salesforce_lead_id`, `pipedrive_deal_id`) links the referral to that record as it is created.
Once linked, changes in your CRM flow to the referral, so you do not need to send updates
yourself.

If your Salesforce org tracks referrals on a custom object, pass that record's ID as
`salesforce_custom_referral_object_id`. It can be sent on its own or together with an
opportunity or lead ID, and every ID sent is linked.

### Idempotency
This endpoint is idempotent on those deal, opportunity, lead and custom referral object IDs.
If a referral already carries the ID you send, that referral is returned with `200 OK` and nothing is created, so a
retried workflow is safe. Nothing else in the request is applied to it; `warnings` lists what was
skipped. If it belongs to a *different* partner than the one you named, you get a `409` instead.
Contact and company IDs are not used for this, because separate referrals can share one company.

### Recording history
`status`, `closed_won_at`, `skip_rewards` and `backfill` let you import referrals that already
happened. They apply only when the referral is created, never on a `200` match.

### Partner contacts and rewards
If every reward on the partner's reward plan pays the partner contact and you name no contact,
the referral would earn nothing, so the request is refused with `422` unless `skip_rewards` is
set. If only some do, the referral is created and the skipped rewards are listed in `warnings`.

Requires `partners_edit` permission.

## Request body

- object
  - `partner_lasso_key` string: Lasso Partner Key of the partner earning this referral (recommended)
  - `partner_slug` string: Partner slug. Editable, so prefer partner_lasso_key.
  - `partner_id` string: Partner ID
  - `partner_name` string: Partner name, exact match. Fails if more than one partner matches.
  - `partner_external_system_type` string: External system to resolve the partner by, e.g. HUBSPOT
  - `partner_external_object_type` string: External object type to resolve the partner by
  - `partner_external_identifier` string: External record ID to resolve the partner by
  - `email` string, required: Contact email of the referred prospect
  - `contact_name` string: Contact name. Falls back to company_name when omitted; one of the two is required.
  - `company_name` string: Company name of the referred prospect
  - `website` string
  - `phone_number` string
  - `amount` number: Estimated deal amount. Overwritten by the CRM value when a CRM opportunity ID is supplied.
  - `expected_close_date` string, date
  - `internal_notes` string
  - `external_notes` string: Notes visible to the partner
  - `expires_at` string, date-time: Defaults to the account's referral expiration setting
  - `fields` object[]: Lead-form answers. Optional: questions the lead form marks as required are enforced for partners submitting through the portal, not for API-key requests.
    - `field_slug` string
    - `response` string
  - `partner_member_slug` string: Attribute the referral to a specific contact under the partner, by Lasso Partner Contact Key. Required when the partner's reward plan pays the Partner Contact: without it those rewards are not applied. Supply at most one `partner_member_*` selector; slug wins over email, which wins over a CRM contact id.
  - `partner_member_email` string, email: Attribute the referral to a partner contact by email, resolved within the named partner.
  - `partner_member_hubspot_contact_id` string: Attribute the referral to a partner contact by HubSpot contact ID. Distinct from `hubspot_contact_id`, which is the *referred prospect's* contact.
  - `partner_member_salesforce_contact_id` string: Attribute the referral to a partner contact by Salesforce contact ID.
  - `partner_member_pipedrive_person_id` string: Attribute the referral to a partner contact by Pipedrive person ID.
  - `status` 'open' | 'accepted' | 'qualified' | 'closed_won' | 'closed_lost' | 'rejected': Create the referral directly in this status, for recording history. Defaults to `open` (or `accepted` when the partner type accepts referrals automatically). Not accepted on update; use the `mark_as_*` fields there. The referral passes through the usual steps to get there, so rewards and invoices for each step are generated as normal. `closed_won` goes through `accepted`, not `qualified`, so a reward paid on qualification is not generated. An unknown value is a `400`. If the status cannot be applied, the referral is still created and a `STATUS_NOT_APPLIED` warning says what state it was left in.
  - `closed_won_at` string, date-time: The historical close date, for a backfilled won deal. Only valid with `status=closed_won`, must be an ISO 8601 timestamp, and cannot be in the future; anything else is a `400`. Without it the close date is the time of the request, and billing that starts from the close date starts from then.
  - `skip_rewards` boolean: Do not copy rewards from the partner's plan and do not generate invoices, for history whose commission was already settled outside Lasso. The suppression is durable: later state changes on this referral will not regenerate them.
  - `backfill` boolean: Do not send notifications, fire webhooks, or sync this referral out to your CRM. Use when recording a referral the source system already holds, so it is not echoed back. Independent of `skip_rewards`: a backfilled referral still earns commission.
  - `hubspot_deal_id` string: HubSpot deal ID. Links the referral and acts as the idempotency key.
  - `hubspot_contact_id` string
  - `hubspot_company_id` string
  - `salesforce_opportunity_id` string: Salesforce opportunity ID. Links the referral and acts as the idempotency key.
  - `salesforce_account_id` string
  - `salesforce_lead_id` string: Salesforce lead ID. Links the referral and acts as the idempotency key.
  - `salesforce_contact_id` string
  - `salesforce_custom_referral_object_id` string: Salesforce ID of a record on your custom referral object (for example a Partner Engagement). Links the referral and acts as an idempotency key, alongside any opportunity or lead ID sent with it.
  - `pipedrive_organization_id` string
  - `pipedrive_person_id` string
  - `pipedrive_deal_id` string: Pipedrive deal ID. Links the referral and acts as the idempotency key.

## Response `200`

A referral already existed for the supplied CRM opportunity ID and was returned unchanged.
Nothing else in your request was applied, so `warnings` lists anything you asked for that
differs from the existing referral. Use `PUT /leads/{identifier}` to change it.

- object
  - `lead` Lead
    - `slug` string
    - `status` 'open' | 'accepted' | 'qualified' | 'closed_won' | 'closed_lost' | 'rejected' | 'churned' | 'expired'
    - `source_type` string, nullable
    - `company_name` string, nullable
    - `contact_name` string, nullable
    - `email` string, nullable
    - `partner_slug` string, nullable
    - `partner_lasso_key` string, nullable: The partner's Lasso Partner Key, the value to send back as `partner_lasso_key`.
    - `partner_member` object, nullable: The partner contact this referral is attributed to, if any.
      - `slug` string
      - `full_name` string, nullable
      - `email` string, nullable
    - `rewards` object[]: The rewards copied onto this referral from the partner's plan. Empty until the referral is accepted. `payee_type` says who each reward is owed to, so you can confirm a partner-contact reward actually landed rather than being skipped for want of a contact.
      - `name` string, nullable
      - `reward_type` string
      - `amount` string
      - `amount_type` string
      - `currency` string
      - `payee_type` 'partner' | 'partner_user'
    - `amount` string: Deal amount.
    - `currency_code` string
    - `expected_close_date` string, date, nullable
    - `co_sold` boolean
    - `deleted_at` string, date-time, nullable
    - `expires_at` string, date-time, nullable
    - `billing_start_date` string, date: The date this referral's billing starts from, after any override is applied.
    - `billing_start_date_override` string, date, nullable: The override set with `billing_start_date` on update, or null when the date is derived from your billing settings.
    - `created_at` string, date-time
    - `updated_at` string, date-time
  - `warnings` object[]: Non-fatal problems with a request that otherwise succeeded. The write happened, but something you asked for was not applied, or the referral will earn less than you may expect. Absent when there is nothing to report. Worth logging: these are the cases that are otherwise only visible as a missing commission weeks later. Messages are prefixed with a stable code: | Code | Returned by | Meaning | |------|-------------|---------| | `SKIPPED_REWARDS` | `POST /leads` (201) | Some rewards on the partner's plan pay the partner contact, and no contact was supplied, so those rewards were not applied. | | `STATUS_NOT_APPLIED` | `POST /leads` (201) | The referral was created, but the requested `status` could not be applied. It stays in the status the message names; finish with `PUT /leads/{identifier}`. | | `EXISTING_REFERRAL_NOT_UPDATED` | `POST /leads` (200) | A referral already carried the CRM record you sent and was returned unchanged. The message lists the fields from your request that were not applied. | | `REWARD_ATTRIBUTION_UNCHANGED` | `PATCH`/`PUT /leads/{identifier}` (200) | The referral was reassigned to another partner contact, but rewards already calculated still pay the previous contact. |
    - `field` string
    - `message` string

## Other responses

- `201`: Referral created. Check `warnings`: the referral was written, but something you asked for may not have been applied.
- `400`: Nothing was written. No partner identifier was supplied, `fields` contained a non-object entry, `status` is not one of the listed values, or `closed_won_at` was sent without `status=closed_won`, is not ISO 8601, or is in the future.
- `401`: Missing or invalid API key
- `403`: API key lacks required permission
- `404`: Partner not found
- `409`: A referral already exists for the supplied CRM ID but belongs to a different partner. Returned instead of a success so a deal reassigned in your CRM cannot silently keep accruing to the original partner.
- `422`: The referral was refused. Messages include `NOT_FOUND` (`partner_member`: no active contact at this partner matches), `REQUIRED` (`partner_member`: every plan reward pays the partner contact and none was named), `MULTIPLE_PARTNERS_FOUND` (`partner_name`), `EXTERNAL_OBJECT_TYPE_REQUIRED` (`partner_external_object_type`: a non-Salesforce partner external lookup without an object type), `HOSTED_FORM_NOT_FOUND` (`base`: no lead form is configured), and validation errors such as a missing email or name.
- `429`: Rate limit exceeded. Wait the number of seconds in `Retry-After`, then retry.

---

[API](https://skmtc.dev/onelasso/apis/lasso-rest-api.md) · [All operations](https://skmtc.dev/onelasso/apis/lasso-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/onelasso/apis/lasso-rest-api/revisions/bbc328f5e2d1?raw)
