api-referencePOST
POSThttps://analytics.flowsery.com/analytics/api/v1/goals

Record a custom goal event. Only name is required; visitorUid, sessionUid, metadata, and timezone are optional.

Bearer Token (workspace token or website API key)

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

ParameterTypeDescription
websiteIdstringWebsite 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.
domainstringWebsite 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

ParameterTypeDescription
visitorUidstringOptional Flowsery visitor ID, typically sourced from the _fs_vid cookie on your own backend.
sessionUidstringOptional Flowsery session ID, typically sourced from the _fs_sid cookie.
nameREQUIREDstringGoal name (lowercase letters, numbers, underscores, and hyphens; max 64 characters).
metadataobjectOptional 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.

Example Request (Node.js)
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");
};
200
{
  "status": "success",
  "data": [{
    "message": "Custom event created successfully"
  }]
}