> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/plausible/analytics/llms.txt
> Use this file to discover all available pages before exploring further.

# List Goals

> Retrieve all goals configured for a site in Plausible Analytics via the Plugins API

## Endpoint

```
GET /api/plugins/v1/goals
```

Retrieves a paginated list of all goals configured for your site. Goals are returned in descending order by ID (newest first).

## Authentication

Requires a Plugins API token with read access.

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication

  ```
  Authorization: Bearer YOUR_API_TOKEN
  ```
</ParamField>

## Query Parameters

<ParamField query="limit" type="integer" default="10">
  Maximum number of goals to return per page

  **Maximum:** 1000 (also the maximum total goals per site)
</ParamField>

<ParamField query="after" type="string">
  Cursor value for forward pagination

  Returned in the pagination metadata of the previous response.
</ParamField>

<ParamField query="before" type="string">
  Cursor value for backward pagination

  Returned in the pagination metadata of the previous response.
</ParamField>

## Response

<ResponseField name="goals" type="array">
  Array of goal objects
</ResponseField>

<ResponseField name="goals[].goal_type" type="string">
  Type of goal

  **Values:**

  * `Goal.CustomEvent` - Custom event goal
  * `Goal.Pageview` - Pageview goal
  * `Goal.Revenue` - Revenue goal (Business plan)
</ResponseField>

<ResponseField name="goals[].goal.id" type="integer">
  Unique identifier for the goal
</ResponseField>

<ResponseField name="goals[].goal.display_name" type="string">
  Human-readable display name

  * For custom events: same as event\_name
  * For pageviews: "Visit {path}"
</ResponseField>

<ResponseField name="goals[].goal.event_name" type="string">
  Event name (for custom event and revenue goals only)
</ResponseField>

<ResponseField name="goals[].goal.path" type="string">
  Page path (for pageview goals only)
</ResponseField>

<ResponseField name="goals[].goal.currency" type="string">
  Currency code (for revenue goals only)

  **Examples:** `USD`, `EUR`, `GBP`
</ResponseField>

<ResponseField name="goals[].goal.custom_props" type="object">
  Custom properties filter configuration (if any)
</ResponseField>

<ResponseField name="meta" type="object">
  Pagination metadata
</ResponseField>

<ResponseField name="meta.after" type="string">
  Cursor for fetching the next page (null if no more pages)
</ResponseField>

<ResponseField name="meta.before" type="string">
  Cursor for fetching the previous page (null if on first page)
</ResponseField>

<ResponseField name="meta.limit" type="integer">
  The limit used for this request
</ResponseField>

## Status Codes

* `200 OK` - Goals retrieved successfully
* `401 Unauthorized` - Missing or invalid API token

## Examples

### List All Goals

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://plausible.io/api/plugins/v1/goals" \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://plausible.io/api/plugins/v1/goals', {
    headers: {
      'Authorization': 'Bearer YOUR_API_TOKEN'
    }
  });

  const data = await response.json();
  console.log(data.goals);
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://plausible.io/api/plugins/v1/goals',
      headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
  )

  goals = response.json()
  print(goals)
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "goals": [
    {
      "goal_type": "Goal.CustomEvent",
      "goal": {
        "id": 123,
        "display_name": "Signup",
        "event_name": "Signup",
        "custom_props": {}
      }
    },
    {
      "goal_type": "Goal.Pageview",
      "goal": {
        "id": 122,
        "display_name": "Visit /pricing",
        "path": "/pricing",
        "custom_props": {}
      }
    },
    {
      "goal_type": "Goal.Revenue",
      "goal": {
        "id": 121,
        "display_name": "Purchase",
        "event_name": "Purchase",
        "currency": "USD",
        "custom_props": {}
      }
    }
  ],
  "meta": {
    "after": null,
    "before": null,
    "limit": 10
  }
}
```

### List Goals with Pagination

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://plausible.io/api/plugins/v1/goals?limit=5" \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://plausible.io/api/plugins/v1/goals?limit=5',
    {
      headers: {
        'Authorization': 'Bearer YOUR_API_TOKEN'
      }
    }
  );

  const data = await response.json();

  // Fetch next page if available
  if (data.meta.after) {
    const nextPage = await fetch(
      `https://plausible.io/api/plugins/v1/goals?limit=5&after=${data.meta.after}`,
      {
        headers: {
          'Authorization': 'Bearer YOUR_API_TOKEN'
        }
      }
    );
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://plausible.io/api/plugins/v1/goals',
      headers={'Authorization': 'Bearer YOUR_API_TOKEN'},
      params={'limit': 5}
  )

  data = response.json()

  # Fetch next page if available
  if data['meta']['after']:
      next_response = requests.get(
          'https://plausible.io/api/plugins/v1/goals',
          headers={'Authorization': 'Bearer YOUR_API_TOKEN'},
          params={
              'limit': 5,
              'after': data['meta']['after']
          }
      )
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "goals": [
    {
      "goal_type": "Goal.CustomEvent",
      "goal": {
        "id": 125,
        "display_name": "Download",
        "event_name": "Download",
        "custom_props": {}
      }
    },
    {
      "goal_type": "Goal.CustomEvent",
      "goal": {
        "id": 124,
        "display_name": "Signup",
        "event_name": "Signup",
        "custom_props": {}
      }
    },
    {
      "goal_type": "Goal.Pageview",
      "goal": {
        "id": 123,
        "display_name": "Visit /pricing",
        "path": "/pricing",
        "custom_props": {}
      }
    },
    {
      "goal_type": "Goal.CustomEvent",
      "goal": {
        "id": 122,
        "display_name": "Purchase",
        "event_name": "Purchase",
        "custom_props": {
          "plan": "premium"
        }
      }
    },
    {
      "goal_type": "Goal.Revenue",
      "goal": {
        "id": 121,
        "display_name": "Purchase",
        "event_name": "Purchase",
        "currency": "EUR",
        "custom_props": {}
      }
    }
  ],
  "meta": {
    "after": "eyJpZCI6MTIxfQ==",
    "before": null,
    "limit": 5
  }
}
```

### Fetch All Goals (Iterating Pages)

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function fetchAllGoals(apiToken) {
    const allGoals = [];
    let after = null;
    
    do {
      const url = new URL('https://plausible.io/api/plugins/v1/goals');
      if (after) url.searchParams.set('after', after);
      url.searchParams.set('limit', '100');
      
      const response = await fetch(url, {
        headers: { 'Authorization': `Bearer ${apiToken}` }
      });
      
      const data = await response.json();
      allGoals.push(...data.goals);
      after = data.meta.after;
    } while (after);
    
    return allGoals;
  }

  const goals = await fetchAllGoals('YOUR_API_TOKEN');
  console.log(`Total goals: ${goals.length}`);
  ```

  ```python Python theme={null}
  import requests

  def fetch_all_goals(api_token):
      all_goals = []
      after = None
      
      while True:
          params = {'limit': 100}
          if after:
              params['after'] = after
          
          response = requests.get(
              'https://plausible.io/api/plugins/v1/goals',
              headers={'Authorization': f'Bearer {api_token}'},
              params=params
          )
          
          data = response.json()
          all_goals.extend(data['goals'])
          after = data['meta']['after']
          
          if not after:
              break
      
      return all_goals

  goals = fetch_all_goals('YOUR_API_TOKEN')
  print(f'Total goals: {len(goals)}')
  ```
</CodeGroup>

## Goal Types

### Custom Event Goal

```json theme={null}
{
  "goal_type": "Goal.CustomEvent",
  "goal": {
    "id": 123,
    "display_name": "Signup",
    "event_name": "Signup",
    "custom_props": {}
  }
}
```

### Pageview Goal

```json theme={null}
{
  "goal_type": "Goal.Pageview",
  "goal": {
    "id": 124,
    "display_name": "Visit /pricing",
    "path": "/pricing",
    "custom_props": {}
  }
}
```

### Revenue Goal (Business Plan)

```json theme={null}
{
  "goal_type": "Goal.Revenue",
  "goal": {
    "id": 125,
    "display_name": "Purchase",
    "event_name": "Purchase",
    "currency": "USD",
    "custom_props": {}
  }
}
```

### Goal with Custom Properties

```json theme={null}
{
  "goal_type": "Goal.CustomEvent",
  "goal": {
    "id": 126,
    "display_name": "Purchase",
    "event_name": "Purchase",
    "custom_props": {
      "plan": "premium",
      "method": "stripe"
    }
  }
}
```

## Notes

* Goals are returned in descending order by ID (newest first)
* Maximum 1,000 goals per site
* Use pagination for sites with many goals
* Goals with custom properties require the Props feature
* Revenue goals are only available on the Business plan
* The `custom_props` field is always present but may be an empty object

## Related Endpoints

* [Create Goal](/api/goals/create) - Create a new goal
* [Delete Goal](/api/goals/delete) - Remove a goal
