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

# Connect a webhook (any CRM, Zapier, Make, n8n)

> Point PipeLime at any HTTP endpoint, choose the fields to send and what to call them, and test it before you save.

export const UiPath = ({children}) => {
  const parts = String(children).split(/\s*(?:→|>)\s*/).filter(Boolean);
  return <span className="pl-path">
      {parts.map((part, index) => <span key={`${index}-${part}`}>
          {index > 0 && <span className="pl-path__sep">→</span>}
          {part}
        </span>)}
    </span>;
};

export const Screenshot = ({id, alt, caption, frame = 'browser', url, marks = [], lang = 'en', workspace = 'northwind-outbound'}) => {
  const src = `/images/screenshots/${lang}/${id}.png`;
  const chrome = url ? `app.pipelime.ai/${workspace}${url}` : 'app.pipelime.ai';
  return <figure className={`pl-shot pl-shot--${frame} not-prose`}>
      <div className="pl-shot__frame">
        {frame !== 'bare' && <div className="pl-shot__bar">
            <span className="pl-shot__dots">
              <span className="pl-shot__dot" />
              <span className="pl-shot__dot" />
              <span className="pl-shot__dot" />
            </span>
            <span className="pl-shot__url">{chrome}</span>
          </div>}
        <div className="pl-shot__media">
          <img src={src} alt={alt} loading="lazy" />
          {marks.map(mark => <span key={mark.n} className="pl-shot__mark" style={{
    left: `${mark.x}%`,
    top: `${mark.y}%`
  }} aria-hidden="true">
              {mark.n}
            </span>)}
        </div>
      </div>
      {caption && <figcaption className="pl-shot__caption">{caption}</figcaption>}
    </figure>;
};

Connect a webhook to send leads to any HTTP endpoint you choose (a CRM, Zapier, Make, n8n, or your own API), with the fields named exactly the way that endpoint expects.

<div className="pl-availability">
  <div className="pl-availability__row">
    <div className="pl-availability__label">Where</div>
    <div className="pl-availability__value"><span className="pl-path">Integrations<span className="pl-path__sep">→</span>Integrations<span className="pl-path__sep">→</span>Apps & CRM</span></div>
  </div>

  <div className="pl-availability__row">
    <div className="pl-availability__label">Your role needs</div>
    <div className="pl-availability__value">Read access to Apps & CRM <code>read-integrations</code>. Admin, Member and Viewer have it by default.</div>
  </div>

  <div className="pl-availability__row">
    <div className="pl-availability__label">To create or change</div>
    <div className="pl-availability__value"><code>create-integrations</code> to add one, <code>update-integrations</code> to change one, on top of the permission above.</div>
  </div>

  <div className="pl-availability__note">If you cannot find this in your sidebar, your workspace may have a custom menu configuration. Contact support and we will check it for you.</div>
</div>

## Before you begin

* A live endpoint URL, reachable from the public internet. One that resolves to a private, loopback or internal address is refused, both by the test and by the save.
* Any token, API key or header value your endpoint needs for authentication, if it needs one.
* Optionally, the vendor's API reference or a single cURL example, if you would rather have the form filled in for you than do it by hand.

## Connect the webhook

<Steps>
  <Step title="Start the connector">
    Go to <UiPath>Integrations → Integrations → Apps & CRM</UiPath>, choose **Add integration**, then choose **Webhook** from the list. This opens the connect dialog: the same one you come back to later if you want to edit it.
  </Step>

  <Step title="Fill the form from their documentation (optional)">
    Instead of copying an endpoint, an auth header and a dozen field names out of another tab by hand, choose **Paste docs**, paste the vendor's API reference or a single cURL example into the box, and choose **Fill the form**. We read it and work out the endpoint, the shape of the authentication and a field mapping. The box is replaced by a confirmation banner, with everything we found filled into the form underneath, ready for you to check. If you had already typed an endpoint, yours is kept.

    A mapping can only point at a lead attribute we define, so the documentation cannot invent one. No credential comes back either, even when the docs show an example token. The token field stays for you to fill in yourself.

    <Screenshot id="integrations/connect-a-webhook--from-docs" url="/integrations" alt="The connect dialog's Fill this in from their documentation panel, its box replaced by an information banner reading “Filled in from the documentation — check it over before saving.”, and underneath it the endpoint, Bearer token authentication with an empty token field, one header and four mapped fields all filled in automatically" caption="One example result: what comes back depends on the documentation you paste. Here the docs described a bearer token, so the auth type came back named and the token itself was left for you to type in." />

    **Fill the form** stays greyed out until there is enough text in the box to read. A line or two will not do it.
  </Step>

  <Step title="Set the endpoint">
    Under **Endpoint**, put the URL in **Endpoint URL**. Set **Method** (POST, PUT, PATCH, GET or DELETE, POST by default) and **Body format**, either **JSON body** or **Form-encoded**.

    <Note>
      Only POST, PUT and PATCH carry a body. Pick GET or DELETE and the payload goes out as a query string instead, so the endpoint has to accept that shape.
    </Note>
  </Step>

  <Step title="Set authentication">
    Under **Authentication**, the next section down, set **Method** to **No authentication**, **Bearer token**, **Custom header**, or **Basic auth**. A custom header also asks for its name. Anything but **No authentication** asks for the credential itself, labeled **Token**, or **user:password** for basic auth.

    <Screenshot id="integrations/connect-a-webhook--authentication" url="/integrations" alt="The Authentication section set to Bearer token, with a Token field whose typed value renders as dots" caption="Once saved, the token never comes back to this screen. Reopen the connector and the field is empty with a masked placeholder." />
  </Step>

  <Step title="Map the fields">
    Under **Field mapping**, choose **Add field** for each value you want to send: pick the lead attribute under **Lead field**, then type your endpoint's own name for it under **Their field name**. Leave the mapping empty and a standard shape goes out instead. With no rows, the section says exactly what that is: "No mapping — we’ll send our standard fields (id, name, email, phone, job title, company, stage, tags…)."

    <Screenshot id="integrations/connect-a-webhook--dialog" url="/integrations" alt="The connect dialog with the endpoint set to a CRM's contacts URL, Method POST and Body format JSON body, and a Field mapping table of four rows sending Lead Information · Lead Email, Lead Information · Lead Name, Lead Information · Job Title and Lead Company · Company Name to the field names email, full_name, title and company" caption="You choose both sides of every row: which lead attribute, and what your own endpoint calls it." />

    <Note>
      Whatever you map, `event`, `lead_id` and `sent_at` ride along with the lead, and nothing you map can overwrite them: the payload is built from your custom fields first, your field mapping next, and those three last.
    </Note>

    Field mapping and custom fields are each capped at 60 rows, headers at 20.
  </Step>

  <Step title="Add custom fields, headers and a name">
    Under **Custom fields & headers**, add any constant that should ride along on every request (a fixed source tag, a list ID) and any extra header your endpoint expects. Under **Record ID**, leave **Store the ID returned by the endpoint** on if you want a lead to show as synced once your endpoint replies with the record it just created; the common reply locations are checked automatically, or you can point at one yourself in **Where to find it (optional)**. Under **Name & icon**, fill in **Name (optional)**, or leave it blank and the connector takes the endpoint's host as its name.
  </Step>

  <Step title="Test it, then save">
    Choose **Send test** to fire a sample payload at the endpoint without saving anything. It carries a made-up lead, not one of yours, but it goes through the same mapping a real push would. The result opens in a window of its own, showing exactly **What we sent** and **Their reply**, so a wrong field name or an empty mapping is obvious before you commit to it.

    When you're ready, choose **Connect**. Unless your own test has just succeeded, the endpoint is tested again at that point, and a connector that fails the test is not saved.
  </Step>
</Steps>

## What happens next

<Check>
  The dialog turns into a **Webhook connected** confirmation. Choose **Done** to close it, and the connector's card is waiting on <UiPath>Integrations → Integrations → Apps & CRM</UiPath>, under the name you gave it or the endpoint's host, with the icon of the service behind that endpoint.
</Check>

From here you can send a lead to it from the **Send Webhook** block in a workflow, or push one by hand from the lead's own page. **Auto-push analyzed leads** starts off for a fresh webhook (the opposite of Slack, which starts it on) because a freshly pasted endpoint cannot be assumed ready for live traffic the moment you save it. Turn it on from the card once you've confirmed the endpoint works. [Auto-push analyzed leads and stage filters](/en/integrations/auto-push-and-stage-filters) covers exactly what that switch does and every reason a push can silently skip a lead.

Come back any time to change any of this: the card's **Edit configuration** icon reopens this same dialog, pre-filled. The token field there is empty behind a masked placeholder: leave it blank to keep the one you already saved. Editing a saved connector, including its auto-push switch, needs the `update-integrations` permission, separate from the one that let you connect it in the first place.

## Troubleshooting

<AccordionGroup>
  <Accordion title="'The endpoint must be a publicly reachable address'">
    An endpoint that resolves to a private, loopback or internal address is refused, at test time and at save time. A host that does not resolve at all is refused the same way, and a redirect is never followed. A 3xx counts as a failure rather than a chance to land somewhere else. Point it at a real public URL. [Webhook testing, delivery rules and record IDs](/en/integrations/webhook-testing-and-delivery-rules) lists every rejection message and what each one means.
  </Accordion>

  <Accordion title="It said the test worked, but nothing arrived">
    A successful test only proves the endpoint accepted the request. Plenty of APIs answer 2xx with an error inside the body, so the reply is read too, and the common shapes of that are reported as a failure rather than a success. Read the endpoint's reply in the test result, and check the field names that went out against what your endpoint actually expects. The Related page below goes through this in full.
  </Accordion>

  <Accordion title="'Could not read that documentation'">
    What you pasted produced no configuration: either the read itself failed, or nothing came back that the form could be filled from. A paste that describes no record-creating call answers "Could not find a webhook endpoint in that documentation." instead. Paste the reference for the call that creates a record, with its fields, plus a cURL example if the docs carry one. Or fill the **Endpoint**, **Authentication** and **Field mapping** sections in by hand.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Webhook testing, delivery rules and record IDs" icon="webhook" href="/en/integrations/webhook-testing-and-delivery-rules">
    Read the test result, understand why a 2xx is not proof, and fix the endpoints we refuse to call.
  </Card>

  <Card title="Zapier, Make, Pipedrive and tools without a native connector" icon="zap" href="/en/integrations/zapier-make-and-other-tools">
    How to connect something we don't list: outbound with a webhook, inbound with the leads API.
  </Card>

  <Card title="CRM and integration blocks" icon="workflow" href="/en/workflows/crm-and-integration-blocks">
    Push a lead to your CRM, post to Slack or call any endpoint, as a step inside a flow.
  </Card>

  <Card title="Auto-push analyzed leads and stage filters" icon="send" href="/en/integrations/auto-push-and-stage-filters">
    What triggers an automatic push, which stages it fires on, and every reason a lead is silently skipped.
  </Card>
</CardGroup>
