Skip to main content
If your website has its own form, your server can send each submission to Goosy Bear as a lead. The submitter becomes a contact in your workspace, automations that start on a new lead run, and the contact goes to your connected GoHighLevel. This page is for your own website, built and hosted by you. If the form is on a page you built in Goosy, you do not need any of this: leads from your Goosy pages are captured already.
The key is a secret. Call this from your server, never from browser code. A key in a page’s JavaScript is visible to everyone who opens the page, and anyone holding it can fill your workspace with leads.

1 · Create a lead-capture key

1

Open Connections → Lead capture

In the app, choose Connections, then Lead capture.
2

Create the key

The key is shown once. Copy it into your server’s secret store straight away. We keep only a fingerprint, so we cannot show it again; if you lose it, create a new one and revoke the old one.
Who can create one: a member who holds Use the API and MCP (see Who can use the API). If you do not see Lead capture, ask an Owner or Admin. A lead-capture key is narrow on purpose:
  • It carries the leads.write scope and can call only leads.capture. It is refused on every other action.
  • It is tied to one workspace, the one you created it in. Leads always land there; you never name a workspace in the request.
  • An ordinary full-access key cannot call leads.capture. Use a lead-capture key.
Other key basics (expiry, revoking, last used) are in Authentication.

2 · Connect GoHighLevel

Leads are sent on to your workspace’s GoHighLevel. Connect it under Connections (it is an OAuth sign-in) so contacts flow there. You can send leads before you connect. Each one is stored and its contact is created in Goosy Bear as normal; its CRM status reads connection_required and nothing is lost. When you connect GoHighLevel, those leads are pushed on the next sweep, in the order they arrived.

3 · The request

Headers

Body fields

A top-level field we do not know is dropped, the lead is still stored, and the response lists the field in ignored_fields. To keep a field of your own, put it inside fields. consent records what the person agreed to, as you send it. We store it with the lead; we do not check it or assume it. If you collect consent, send it. You are responsible for collecting consent on your form and for sending it truthfully. Leaving consent out does not mark anyone as consenting.

4 · The response

A stored lead answers 200:
  • lead_id is the stored lead.
  • contact_id is the workspace contact the submitter became. It can be null when the email names no one we can make a contact for.
  • submission_id names this submission: your Idempotency-Key or submission_id, or one we made when you sent neither. Send it on a retry so the lead is not stored twice.
  • replayed is true when this was a retry of a submission already stored (see below). Nothing new was written.
  • ignored_fields lists every field we dropped: unknown top-level fields by name, unknown campaign keys as utm.<key>. Empty when nothing was dropped.
  • workspace is the slug of the workspace the lead went to.
The answer comes back once the lead is stored, the contact exists and the automations for a new lead have been started.

5 · Refusals

Refusals follow the usual shape: ok: false, a code and a message written to be read. Branch on ok, not on the status code. A refused lead was not stored, except where noted.

Refused by the action

These answer 200 with "ok": false.

Refused at the door

6 · Idempotency and retries

A network can fail after we stored the lead but before you heard back. Name each submission with Idempotency-Key (or submission_id), and send the same value when you retry. The key is optional. Without one, each call is stored as a new submission and the response’s submission_id names it; send that value on any later retry. A call whose response you never received cannot be matched that way, so if your server retries on network errors, send your own key.
  • A retry with the same key returns the first answer, with "replayed": true, and stores nothing again. No second lead, no second automation, no second CRM push.
  • Choose one stable id per form submission, such as the id of the row you saved for it, and reuse it only for retries of that same submission. A different submission under a key you already used is refused with idempotency_key_reused.
  • Keys are honoured for at least 24 hours.
  • Retry on a network error, a 429 (after Retry-After) or 5xx, and on leads.capture_unavailable, idempotency_in_progress and idempotency_unavailable. Do not retry invalid_arguments and the other errors that need a change from you.

7 · Limits

There is no CAPTCHA on this door. Because your server holds the key, spam protection on your form (a CAPTCHA, a honeypot, your own rate limit) belongs on your side before you call us. If a key leaks, revoke it and create another.

8 · What happens after a lead arrives

1

The lead is stored

It is saved to your workspace with the form name, fields, campaign data and consent as you sent them.
2

The submitter becomes a contact

We find the contact with that email or create one. The response carries its contact_id.
3

Automations start

Automations whose trigger is Lead captured run for the new lead. If you sent form, an automation can be set to start only on that form.
4

The contact goes to GoHighLevel

With GoHighLevel connected, the contact is pushed to it. With none connected, the lead waits as connection_required and is pushed after you connect. A push that fails for another reason is retried.
An automation may email or text the person, and the contact’s details reach your CRM. A lead sent cannot be unsent from the API, so test with an address you control (below).

9 · Copy-paste examples

Run these on your server. Keep the key in an environment variable.

Node (fetch)

cURL

10 · Test it

1

Send one lead to an address you control

Use the cURL call above with your own email and a fresh Idempotency-Key. You should get "ok": true and a lead_id.
2

Check it arrived

Open the contact in your workspace. If you have a Lead captured automation, confirm it ran.
3

Send the same call again

Same Idempotency-Key. The answer is the same ids with "replayed": true, and no second lead appears.

Troubleshooting

The key is missing, mistyped, revoked or expired. Check for a stray space or newline in your secret, and look at the key under Connections.
You sent a full-access key to leads.capture, or a lead-capture key to another action. Use a key from Connections → Lead capture for this call.
The email is not a valid address. Check what the person typed, and that your form sends the email field and not another one.
Read the issues list in the reply. The usual causes are a missing email, or a value that is too long or not a string.
We do not know that top-level field, so it was dropped and the lead was stored without it. Move it inside fields to keep it.
GoHighLevel is probably not connected yet. Connect it under Connections and the waiting leads are pushed on the next sweep.
The automation must start on Lead captured. If it is limited to one form, the form you send must match.
You passed 60 calls a minute on this key. Wait for Retry-After, then retry with the same Idempotency-Key.
If you still need help, send support the x-request-id from the response.