https://analytics.flowsery.com/analytics/api/v1/goalsRecord a custom goal event. Only name is required; visitorUid, sessionUid, metadata, and timezone are optional.
Workspace Tokens Need a Website Selector
Workspace API tokens can access every website in the workspace. Pass either <code>websiteId</code> or <code>domain</code> so Flowsery knows which website to query or mutate. Website API keys are already scoped to one website, so the selector can be omitted.Website Selector
| Parameter | Type | Description |
|---|---|---|
websiteId | string | Website ID to use with a workspace API token. Include this field in the JSON body unless you provide domain. Omit when authenticating with a website API key. |
domain | string | Website domain to use with a workspace API token when websiteId is not provided. Include this field in the JSON body. Omit when authenticating with a website API key. |
Request Body
| Parameter | Type | Description |
|---|---|---|
visitorUid | string | Optional Flowsery visitor ID, typically sourced from the _fs_vid cookie on your own backend. |
sessionUid | string | Optional Flowsery session ID, typically sourced from the _fs_sid cookie. |
nameREQUIRED | string | Goal name (lowercase letters, numbers, underscores, and hyphens; max 64 characters). |
metadata | object | Optional string key-value pairs stored with the completion. Up to 10 pairs. |
Metadata Field Rules
<strong>Keys:</strong> Short lowercase names such as <code>plan</code> or <code>signup_source</code> keep reports readable. The API does not check key format.
<strong>Values:</strong> Strings, stored as sent. Do not put personal data such as emails in metadata.
<strong>Limit:</strong> Up to 10 pairs per event. More than 10 answers <code>400 Bad Request</code>.
No Existing Pageview Required
The goal is created on first use, and a completion does not need an earlier pageview. Without visitorUid the completion is recorded as anonymous. Each call adds one completion, so repeating it counts the goal twice.Error Responses
<strong>400 Bad Request</strong> -- The payload is invalid, for example a name with uppercase letters or spaces, or more than 10 metadata pairs.
<strong>404 Not Found</strong> -- The websiteId or domain does not match a website this credential can reach.
const handler = async (req, res) => {
const _fs_vid = req.cookies._fs_vid;
const _fs_sid = req.cookies._fs_sid;
const response = await fetch(
"https://analytics.flowsery.com/analytics/api/v1/goals",
{
method: "POST",
headers: {
Authorization: `Bearer ${FLOWSERY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
websiteId: process.env.FLOWSERY_WEBSITE_ID,
visitorUid: _fs_vid,
sessionUid: _fs_sid,
name: "newsletter_signup",
metadata: {
plan: "pro",
form: "footer",
},
}),
}
);
const result = await response.json();
res.status(200).send("Goal tracked");
};{
"status": "success",
"data": [{
"message": "Custom event created successfully"
}]
}