Skip to main content

Endpoint

PUT /api/plugins/v1/goals
Creates a new goal or returns an existing goal if it already exists (upsert behavior). Goals are used to track conversions for custom events or pageviews.

Authentication

Requires a Plugins API token with write access.
Authorization
string
required
Bearer token for authentication
Authorization: Bearer YOUR_API_TOKEN

Request Body

The request body accepts either a single goal or multiple goals (for bulk creation).

Single Goal Creation

goal_type
string
required
Type of goal to createOptions:
  • Goal.CustomEvent - Track custom events
  • Goal.Pageview - Track pageview conversions
  • Goal.Revenue - Track revenue goals (requires Business plan)
goal
object
required
Goal configuration object (structure varies by goal_type)

Custom Event Goal

goal.event_name
string
required
Name of the custom event to trackRequirements:
  • Maximum length: 120 characters
  • Cannot be engagement (reserved)
  • Will be trimmed of leading/trailing whitespace
Examples: Signup, Purchase, Download
goal.custom_props
object
Custom properties filter for the goal (up to 3 properties)Requirements:
  • Maximum 3 properties per goal
  • Keys: 1-300 characters
  • Values: 1-2000 characters
  • Both keys and values must be strings
Example:
{
  "plan": "premium"
}

Pageview Goal

goal.path
string
required
Page path to track as a goalRequirements:
  • Must start with /
  • Will be trimmed of leading/trailing whitespace
  • Leading slash is automatically added if missing
Examples: /pricing, /blog/*, /thank-you
goal.custom_props
object
Custom properties filter for the goal (up to 3 properties)

Revenue Goal (Business Plan)

goal.event_name
string
required
Name of the revenue event to track
goal.currency
string
required
Currency code for revenue trackingRequirements:
  • Must be a valid ISO 4217 currency code
  • Cannot be changed once the goal is created
  • Each event name can only have one currency
Examples: USD, EUR, GBP
goal.custom_props
object
Custom properties filter for the goal (up to 3 properties)

Bulk Goal Creation

goals
array
Array of goal objects (maximum 8 goals)Each goal object follows the same structure as single goal creation.

Response

goals
array
Array of created or retrieved goals
goals[].goal_type
string
Type of goal: Goal.CustomEvent, Goal.Pageview, or Goal.Revenue
goals[].goal.id
integer
Unique identifier for the goal
goals[].goal.display_name
string
Human-readable display name for the goal
  • For custom events: same as event_name
  • For pageviews: “Visit
goals[].goal.event_name
string
Event name (for custom event and revenue goals)
goals[].goal.path
string
Page path (for pageview goals)
goals[].goal.currency
string
Currency code (for revenue goals)
goals[].goal.custom_props
object
Custom properties filter configuration

Status Codes

  • 201 Created - Goal(s) created or retrieved successfully
  • 400 Bad Request - Invalid request parameters
  • 401 Unauthorized - Missing or invalid API token
  • 402 Payment Required - Revenue goals require Business plan upgrade
  • 422 Unprocessable Entity - Validation error

Examples

Create Custom Event Goal

curl -X PUT https://plausible.io/api/plugins/v1/goals \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "goal_type": "Goal.CustomEvent",
    "goal": {
      "event_name": "Signup"
    }
  }'
Response:
{
  "goals": [
    {
      "goal_type": "Goal.CustomEvent",
      "goal": {
        "id": 123,
        "display_name": "Signup",
        "event_name": "Signup",
        "custom_props": {}
      }
    }
  ]
}

Create Pageview Goal

curl -X PUT https://plausible.io/api/plugins/v1/goals \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "goal_type": "Goal.Pageview",
    "goal": {
      "path": "/thank-you"
    }
  }'
Response:
{
  "goals": [
    {
      "goal_type": "Goal.Pageview",
      "goal": {
        "id": 124,
        "display_name": "Visit /thank-you",
        "path": "/thank-you",
        "custom_props": {}
      }
    }
  ]
}

Create Goal with Custom Properties

curl -X PUT https://plausible.io/api/plugins/v1/goals \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "goal_type": "Goal.CustomEvent",
    "goal": {
      "event_name": "Purchase",
      "custom_props": {
        "plan": "premium"
      }
    }
  }'
Response:
{
  "goals": [
    {
      "goal_type": "Goal.CustomEvent",
      "goal": {
        "id": 125,
        "display_name": "Purchase",
        "event_name": "Purchase",
        "custom_props": {
          "plan": "premium"
        }
      }
    }
  ]
}

Create Revenue Goal (Business Plan)

curl -X PUT https://plausible.io/api/plugins/v1/goals \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "goal_type": "Goal.Revenue",
    "goal": {
      "event_name": "Purchase",
      "currency": "USD"
    }
  }'
Response:
{
  "goals": [
    {
      "goal_type": "Goal.Revenue",
      "goal": {
        "id": 126,
        "display_name": "Purchase",
        "event_name": "Purchase",
        "currency": "USD",
        "custom_props": {}
      }
    }
  ]
}

Bulk Create Goals

curl -X PUT https://plausible.io/api/plugins/v1/goals \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "goals": [
      {
        "goal_type": "Goal.CustomEvent",
        "goal": {
          "event_name": "Signup"
        }
      },
      {
        "goal_type": "Goal.Pageview",
        "goal": {
          "path": "/pricing"
        }
      }
    ]
  }'

Error Responses

Validation Error

{
  "errors": {
    "event_name": ["can't be blank"],
    "currency": ["is invalid"]
  }
}

Maximum Goals Reached

{
  "errors": {
    "event_name": ["Maximum number of goals reached"]
  }
}
Note: Each site can have a maximum of 1,000 goals.

Upgrade Required (Revenue Goals)

{
  "error": "Revenue Goals is part of the Plausible Business plan. To get access to this feature, please upgrade your account."
}

Currency Mismatch

{
  "errors": {
    "event_name": ["'Purchase' (with currency: EUR) has already been taken"]
  }
}
This error occurs when trying to create a revenue goal with a different currency for an event name that already exists with another currency.

Notes

  • Goals are created with upsert behavior - if a goal already exists, it will be returned instead of creating a duplicate
  • Display names are automatically generated: event name for custom events, “Visit ” for pageviews
  • Leading and trailing whitespace in event names and paths is automatically trimmed
  • Pageview goals automatically get a leading / if not provided
  • Revenue goals cannot be created for consolidated views
  • Once created, a revenue goal’s currency cannot be changed
  • Custom properties require the Props feature (available on certain plans)

Build docs developers (and LLMs) love