Last updated July 27, 2026
The JourneyFuse API lets outside tools create data in your workspace automatically. Where Webhooks send data out of JourneyFuse when something happens, the API lets you send data in — for example, pushing a new Facebook lead into JourneyFuse the moment it comes in, with no manual copying.
If you use Make.com, Zapier, or your own code to move data between tools, this is how you connect them to JourneyFuse.
The API is currently in beta and covers the most common automation needs:
| Action | Method | Endpoint |
|---|---|---|
| Verify your key / get workspace info | GET | /api/v1/me |
| Create a lead | POST | /api/v1/leads |
| Create a client | POST | /api/v1/clients |
| Find clients (by email, or list recent) | GET | /api/v1/clients |
| Create a trip | POST | /api/v1/trips |
| Get a trip by ID | GET | /api/v1/trips/:id |
| Create a client and a trip in one call | POST | /api/v1/intake (also /api/v1/bookings) |
The base URL is https://journeyfuse.com (or your agency's custom domain, if you have one).
jf_live_)Your full key is shown only once, right after you create it. Copy it somewhere safe before closing the dialog. If you lose it, just create a new one and delete the old.
Treat a key like a password. You can revoke one at any time from the same page.
Every key belongs to one workspace, and how much of that workspace it reaches depends on who created it.
| Who creates it | Scope | What the key can reach |
|---|---|---|
| An advisor on a team | Advisor only | That advisor's own clients, leads, and trips |
| An agency owner or admin | Agency-wide | Every record in the workspace |
| A solo agency (one member) | Agency-wide | Everything, since it is all yours anyway |
This matters most at a host agency, where hundreds of independent advisors share one JourneyFuse workspace. An advisor's key can never read a colleague's clients, and a lookup for someone else's client comes back empty rather than telling you it exists somewhere.
If you are on a team, your key behaves like this:
GET /api/v1/clients lists your clients, and another advisor's trip returns 404 even with the correct ID.agent_email and agent_id are accepted so the same request body works everywhere, but leads always land on you. Use an agency-wide key to route leads to other advisors.Owners and admins see every key in the workspace on the Settings → API page, labeled Advisor only or Agency-wide. Advisors see only their own.
Send your key on every request, in either of these headers:
Authorization: Bearer jf_live_your_key_here
or
x-api-key: jf_live_your_key_here
To check that a key works, call the me endpoint:
curl https://journeyfuse.com/api/v1/me \
-H "Authorization: Bearer jf_live_your_key_here"
A working key returns your workspace:
{
"workspace": { "id": "...", "name": "Your Agency", "kind": "agency" },
"scopes": ["*"]
}
This is the most common use: pushing a new inquiry into JourneyFuse so it shows up in your Leads pipeline at stage New.
Endpoint: POST /api/v1/leads
Body fields:
| Field | Required | Notes |
|---|---|---|
first_name | Yes* | Required unless you send name |
last_name | Yes* | Required unless you send name |
name | Yes* | Alternative to the pair above. A single full name, split on the first space — "Jamie Rivera" becomes first Jamie, last Rivera. Also accepted as full_name |
email | No | |
phone | No | |
source | No | Where the lead came from, e.g. "Facebook Lead Ads" |
destination | No | Where they want to travel |
notes | No | Any extra detail from the form |
agent_email | No | Route the lead to a specific agent by their JourneyFuse email |
agent_id | No | Route the lead to a specific agent by their user ID |
*Send either first_name + last_name or name. If you send name
along with an explicit first_name or last_name, the explicit field wins.
If name is a single word ("Prince"), the lead is stored with a blank last
name. This is what makes the endpoint work with chat platforms like ManyChat,
Messenger and Instagram, where contacts frequently have no Last Name.
Example request:
curl -X POST https://journeyfuse.com/api/v1/leads \
-H "Authorization: Bearer jf_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jamie",
"last_name": "Rivera",
"email": "jamie@example.com",
"phone": "+1 555 123 4567",
"source": "Facebook Lead Ads",
"destination": "Maui",
"notes": "Honeymoon, late September, budget around $8k",
"agent_email": "rebecca@youragency.com"
}'
Example request — chat platforms (ManyChat, Messenger, Instagram):
These platforms usually expose one name field, or a Last Name that is often
empty. Map the whole name into name and the request keeps working either way:
curl -X POST https://journeyfuse.com/api/v1/leads \
-H "Authorization: Bearer jf_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "{{first_name}} {{last_name}}",
"email": "{{email}}",
"phone": "{{phone}}",
"source": "ManyChat"
}'
If the contact's Last Name is empty, name arrives as just their first name and
the lead is created with a blank last name — no error, no failed automation.
Successful response (201 Created):
{
"data": {
"id": "a1b2c3d4-...",
"first_name": "Jamie",
"last_name": "Rivera",
"email": "jamie@example.com",
"phone": "+1 555 123 4567",
"source": "Facebook Lead Ads",
"stage": "new",
"destination": "Maui",
"assigned_to": "9a26f4ee-...",
"assignment_status": "pending",
"created_at": "2026-06-17T14:30:00.000Z"
},
"assignment": { "requested": "rebecca@youragency.com", "matched": true }
}
The new lead appears in your Leads pipeline immediately, and a lead.created webhook fires if you have one set up.
This applies to agency-wide keys. On an advisor-scoped key these fields are ignored and the lead is assigned to you (see Key Scope).
Pass agent_email and/or agent_id to route an incoming lead straight to a specific agent. The identifier is matched against your agency's members (email match is case-insensitive):
assignment.matched is false, so your automation can flag it.If you send both agent_email and agent_id, the ID is tried first and the email is used as a fallback.
This walks through the exact setup for sending Facebook lead-ad leads straight into JourneyFuse, replacing a tool like ClickUp in the middle.
https://journeyfuse.com/api/v1/leadsPOSTAuthorizationBearer jf_live_your_key_hereapplication/json{
"first_name": "{{first_name}}",
"last_name": "{{last_name}}",
"email": "{{email}}",
"phone": "{{phone_number}}",
"source": "Facebook Lead Ads",
"destination": "{{destination}}"
}
That is the whole flow. Every new Facebook lead now lands in JourneyFuse automatically, tagged with the source so you know where it came from. The same HTTP module approach works for any tool that can send an HTTP request, including Zapier's Webhooks by Zapier → POST action.
Endpoint: POST /api/v1/clients
Required: first_name, last_name. Optional: email, phone, household_id. If you leave household_id out, a household is created automatically (the same as adding a client in the app).
curl -X POST https://journeyfuse.com/api/v1/clients \
-H "Authorization: Bearer jf_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "first_name": "Sam", "last_name": "Lee", "email": "sam@example.com" }'
Endpoint: GET /api/v1/clients
List the most recent clients, or look one up by email:
# Most recent (up to 100; default 20)
curl "https://journeyfuse.com/api/v1/clients?limit=50" \
-H "Authorization: Bearer jf_live_your_key_here"
# Find by email
curl "https://journeyfuse.com/api/v1/clients?email=sam@example.com" \
-H "Authorization: Bearer jf_live_your_key_here"
Endpoint: POST /api/v1/trips
Required: name. Optional: client_id, start_date, end_date, destination, status (defaults to planning). If you pass a client_id, it must belong to your workspace.
curl -X POST https://journeyfuse.com/api/v1/trips \
-H "Authorization: Bearer jf_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Rivera Honeymoon - Maui",
"client_id": "a1b2c3d4-...",
"start_date": "2026-09-20",
"end_date": "2026-09-28",
"destination": "Maui"
}'
Endpoint: POST /api/v1/intake — also reachable at POST /api/v1/bookings
Most booking automations need the same two things: find or create the client, then create a trip for them. Doing that with the endpoints above takes three calls (GET /api/v1/clients?email=…, then POST /api/v1/clients if nothing came back, then POST /api/v1/trips), plus branching logic in Make.com or Zapier to handle the "already a client" case.
This endpoint does all of it in one request. Send the person's name and email, and JourneyFuse either reuses the client you already have or creates a new one, then creates a trip linked to them.
This does not create booking components. Despite the older
/api/v1/bookingspath, this endpoint creates a client and a trip — not hotels, flights, cruises, or any other booking line item on a trip. There is no API for adding booking components yet; those are added in the app./api/v1/intakeis the same endpoint under a name that says what it actually does, and it is the one to use in new automations. The/api/v1/bookingspath keeps working exactly as before, so nothing you have already built needs to change.
Body fields:
| Field | Required | Notes |
|---|---|---|
first_name | Yes | |
last_name | Yes | |
email | No | This is what dedupe keys on. Strongly recommended — see below |
phone | No | Only used when a new client is created |
event_name | No | What they booked, e.g. "3-Hour Planning Session". Used in the auto-generated trip name |
start_date | No | Trip start. Full ISO timestamps are fine — see below |
end_date | No | Trip end |
destination | No | Where they're going |
trip_name | No | Overrides the auto-generated trip name |
source | No | Defaults to "Calendly". Echoed back in the response |
email, JourneyFuse looks for an existing client with that email in your workspace. The match is case-insensitive, so Sam@Example.com finds sam@example.com. If more than one matches, the oldest one wins.email out, there is nothing to dedupe on and a new client is created every time. Send the email whenever your source system has one.The response tells you which happened: client_created is true for a brand-new client and false when an existing one was reused.
trip_name, it's composed from what you did send, joined with em dashes: Jamie Rivera — 3-Hour Planning Session — Sep 20, 2026. Parts you leave out are skipped, so a request with just a name produces a trip named Jamie Rivera.start_date and end_date accept a plain date (2026-09-20) or a full ISO timestamp (2026-09-20T14:00:00.000000Z), which is what Calendly sends. Either way only the date is stored, so you can map Calendly's field straight across without reformatting it.source is echoed back in the response so your automation can branch on it, but it is not stored on the trip — put anything you need to keep in trip_name or event_name.Example request:
curl -X POST https://journeyfuse.com/api/v1/intake \
-H "Authorization: Bearer jf_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jamie",
"last_name": "Rivera",
"email": "jamie@example.com",
"phone": "+1 555 123 4567",
"event_name": "3-Hour Planning Session",
"start_date": "2026-09-20T14:00:00.000000Z",
"end_date": "2026-09-28",
"destination": "Maui",
"source": "Calendly"
}'
Successful response (201 Created):
{
"data": {
"client": {
"id": "a1b2c3d4-...",
"first_name": "Jamie",
"last_name": "Rivera",
"email": "jamie@example.com",
"phone": "+1 555 123 4567",
"household_id": "b2c3d4e5-..."
},
"trip": {
"id": "c3d4e5f6-...",
"name": "Jamie Rivera — 3-Hour Planning Session — Sep 20, 2026",
"client_id": "a1b2c3d4-...",
"start_date": "2026-09-20",
"end_date": "2026-09-28",
"destination": "Maui",
"status": "planning",
"created_at": "2026-07-27T14:30:00.000Z"
},
"client_created": true,
"source": "Calendly"
}
}
Both client.created and trip.created webhooks fire — except that client.created is skipped when an existing client was reused, since no client was created.
Same shape as the Facebook flow above: Calendly → Watch Events, then HTTP → Make a request pointed at https://journeyfuse.com/api/v1/intake with your Authorization header and this body:
{
"first_name": "{{invitee_first_name}}",
"last_name": "{{invitee_last_name}}",
"email": "{{invitee_email}}",
"event_name": "{{event_type_name}}",
"start_date": "{{event_start_time}}",
"source": "Calendly"
}
Book a test appointment on your own Calendly link, then check Trips in JourneyFuse for the new trip before turning the scenario on.
Errors come back as JSON with a consistent shape:
{ "error": "invalid_input", "message": "first_name and last_name are required (or send name / full_name).", "fields": { "first_name": "required", "last_name": "required" } }
| Status | What it means |
|---|---|
400 | Missing or invalid fields, or the body was not valid JSON |
401 | Missing key, or the key is wrong or revoked |
404 | The record was not found in your workspace |
500 | Something went wrong on our end |
/api/v1/me first so you know the key works before building the rest of the automation/api/v1/intake when a booking should produce both a client and a trip — it dedupes the client for you, so repeat customers don't pile up as duplicates. Remember it creates a client and a trip, not booking components like hotels or flights.source on leads (like "Facebook Lead Ads") so you can tell at a glance where each one came fromSet agency-wide terms, let each advisor use their own, and control whether sub-agents inherit your agency terms — applied consistently across proposals, invoices, and service agreements.
Send an independent contractor agreement for e-signature, auto-fill details with merge fields, counter-sign it as the agency, and download the fully executed PDF.
Automatically send real-time event data to external tools like Zapier, Make.com, or your own API whenever something happens in JourneyFuse.