# Fathom Analytics API — v1 > Take complete control of your Fathom account, privately. - **Base URL:** `https://api.usefathom.com/v1` - **Authentication:** Bearer token — send `Authorization: Bearer YOUR_API_TOKEN` - **Headers:** send `Accept: application/json` so errors are returned as JSON - **OpenAPI schema:** https://usefathom.com/api/openapi.json - **Human-readable reference:** https://usefathom.com/api/v1 --- ## Fathom Analytics API The Fathom Analytics API allows you to take complete control of your Fathom account. You can control all entities within the account and generate ad-hoc custom reports. It's an incredibly powerful API, and we've tried to cater to every possible use case. Each API request counts against your total monthly pageviews. So if you make 10 Create Site requests, that will count in the same way that 10 pageviews would. We do this because we want to give you the flexibility to use our API how you wish, and we want to ensure it's sustainable without us having to raise plan prices. When running complex aggregation queries that are unique (haven't been run before by any user), you will experience a slight lag the first time you run the query. This is because our database engine has to create a "query plan" to find the most optimal way to run what you're asking for. After that, it will be rapid. The base URL for all v1 endpoints is `https://api.usefathom.com/v1`. > **Please note:** See our [community guidelines](/legal/guidelines) for guidance about what you can and can't do when creating plugins, integrations and connections to our API. ## Rate limits The rate limits for our API are: - **2,000 requests per hour** on the Account, Sites, Events and Milestones endpoints. - **10 requests per minute** on the Aggregation and Current Visitors endpoints. Rate limits are applied per user. If you need more, please contact [support@usefathom.com](mailto:support@usefathom.com) and we can discuss custom plans. ## Create a token To create a token for our API, go to [https://app.usefathom.com/api](https://app.usefathom.com/api) and click `Create new`. - Click `Create new` from the API page. - Give your token a name, and set permissions (Admin, read only (all sites), or site-specific). - Click `Save changes`. - Write down your API token and save it in a safe place. You won't be able to retrieve your token once you navigate away from that page. ## Authentication To connect to our API, you must use the `Authorization` header with a bearer token. This can be obtained from your dashboard, under Settings → API. Your API key has complete access to your account (depending on the permissions you set), so please protect it. You should also send `Accept: application/json` so that errors are returned as JSON. ## Pagination All top-level API resources allow you to fetch records in bulk via our "list" methods. These list methods share a common, cursor-based pagination structure. We've taken inspiration from the excellent Stripe API, so this will be familiar to a lot of you. You can paginate using either `starting_after` or `ending_before` (but not both at once): - When you use `starting_after`, we sort records in chronological order, allowing you to page from the start of time up until the current day. - When you use `ending_before`, we sort records in reverse chronological order, effectively working backwards from the object ID you give us. Every list response is wrapped in a list object. The `has_more` boolean tells you whether another page is available, and the value to pass as your next cursor is the `id` of the first or last item in `data`. All list endpoints accept these query string parameters: - `limit` — the number of objects to return, between 1 and 100 (default 10). - `starting_after` — an object ID that defines your place in the list, paging forwards. - `ending_before` — an object ID that defines your place in the list, paging backwards. **List response shape** ```json { "object": "list", "url": "/v1/sites", "has_more": true, "data": [ { "...": "..." } ] } ``` ## Errors When we detect a problem with your request, we return an HTTP `400` or `401` response. Make sure you've set `Accept: application/json` in your request headers so that errors come back as JSON. General errors return a single `error` key with a human-readable message. Validation errors (for example, a missing required field) return an `errors` object keyed by field name. **General error** ```json { "error": "This token doesn't have permission to access this endpoint" } ``` **Validation error** ```json { "errors": { "name": [ "The name field is required." ] } } ``` ## Issues If you run into any issues, or have any ideas, please [let us know](mailto:support@usefathom.com). We want this API to be fast, sustainable and powerful, and we're all ears on making it better. --- ## Account Information about the account and token behind your API key. ### Get account ```http GET /account ``` Retrieve information about the account that owns the API key. **Permissions:** Requires a token with full account access (the `*` scope). **Returns:** An account object. **Example request** ```bash curl "https://api.usefathom.com/v1/account" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": 500302232, "object": "account", "name": "Homer Simpson", "email": "homer@simpsonsfamily.doh" } ``` ### Get token ```http GET /token ``` Retrieve metadata about the API token used to make the request, including its name, permissions (abilities), token-format version and timestamps. Your secret token value is never returned. **Permissions:** Any valid API token. **Returns:** A token object. **Example request** ```bash curl "https://api.usefathom.com/v1/token" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "name": "Production server", "version": 4, "abilities": [ "*" ], "last_used_at": "2024-01-15 09:24:00", "expires_at": null, "created_at": "2024-01-01 12:00:00", "updated_at": "2024-01-15 09:24:00" } ``` --- ## Sites Create and manage the sites in your Fathom account. ### List sites ```http GET /sites ``` Return a list of all sites this API key owns. Sites are sorted by `created_at` ascending to allow you to paginate with ease. **Permissions:** Requires read access to all sites (`all-sites-readonly`) or full account access. **Returns:** A list of site objects. **Parameters** - `limit` (integer, query, optional) — A limit on the number of objects to be returned, between 1 and 100. Default: `10`. - `starting_after` (string, query, optional) — A cursor for use in pagination. `starting_after` is an object ID that defines your place in the list. For example, if you make a list request and receive 10 objects ending with `obj_foo`, your subsequent call can include `starting_after=obj_foo` to fetch the next page. - `ending_before` (string, query, optional) — A cursor for use in pagination, working in the opposite direction to `starting_after`. `ending_before` is an object ID that defines your place in the list. **Example request** ```bash curl "https://api.usefathom.com/v1/sites" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "object": "list", "url": "/v1/sites", "has_more": false, "data": [ { "id": "CDBUGS", "object": "site", "name": "Bugs Bunny Portfolio", "sharing": "none", "created_at": "2020-07-27 12:01:01", "timezone": "America/New_York" } ] } ``` ### Get site ```http GET /sites/{site_id} ``` Return a single site. **Permissions:** Requires read access to the site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** A site object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` **Example request** ```bash curl "https://api.usefathom.com/v1/sites/CDBUGS" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "CDBUGS", "object": "site", "name": "Bugs Bunny Portfolio", "sharing": "none", "created_at": "2020-07-27 12:01:01", "timezone": "America/New_York" } ``` ### Create site ```http POST /sites ``` Create a site. **Permissions:** Requires full account access (`*`). **Returns:** A site object. **Parameters** - `name` (string, body, required) — The name of the website. Any string (up to 255 characters) is acceptable, and it doesn't have to match the website URL. Example: `Daffy's Website` - `sharing` (string, body, optional) — The sharing configuration. Supported values are `none`, `private` or `public`. One of: `none`, `private`, `public`. Default: `none`. - `share_password` (string, body, Required if sharing is private) — When sharing is set to `private`, you must also send a password to access the site with (up to 255 characters). - `timezone` (string, body, optional) — The site's reporting timezone as a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) (e.g. `America/New_York`). If omitted, the site inherits your account's default timezone. - `multi_domain` (boolean, body, optional) — Set to `true` to allow this site to track multiple domains. Default: `false`. - `multi_domain_option` (string, body, Required if multi_domain is true) — How multi-domain data is grouped. Supported values are `combined` (report all domains together) or `separate` (report each domain individually). One of: `combined`, `separate`. **Example request** ```bash curl -X POST "https://api.usefathom.com/v1/sites" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "Bugs Bunny Portfolio" }' ``` **Example response (`200`)** ```json { "id": "GCDFS", "object": "site", "name": "Acme Inc", "sharing": "none", "created_at": "2021-08-10 00:45:43", "timezone": "America/New_York" } ``` ### Update site ```http POST /sites/{site_id} ``` Update a site. Send only the fields you want to change. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** A site object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `name` (string, body, optional) — The name of the website (up to 255 characters). - `sharing` (string, body, optional) — The sharing configuration. Supported values are `none`, `private` or `public`. One of: `none`, `private`, `public`. - `share_password` (string, body, Required if sharing is private) — When sharing is set to `private`, you must also send a password to access the site with (up to 255 characters). - `timezone` (string, body, optional) — The site's reporting timezone as a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) (e.g. `America/New_York`). Reporting for this site will use this timezone. - `multi_domain` (boolean, body, optional) — Set to `true` to allow this site to track multiple domains. - `multi_domain_option` (string, body, Required if multi_domain is true) — How multi-domain data is grouped: `combined` or `separate`. One of: `combined`, `separate`. **Example request** ```bash curl -X POST "https://api.usefathom.com/v1/sites/CDBUGS" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "GCDFS", "object": "site", "name": "Acme Holdings Inc", "sharing": "private", "created_at": "2021-08-10 00:45:43", "timezone": "America/New_York" } ``` ### Wipe site ```http DELETE /sites/{site_id}/data ``` > **Deprecated.** This endpoint has been retired and now returns `410 Gone`. It is no longer possible to wipe a site's data via the API. Previously wiped all pageviews and event completions from a website. This endpoint is no longer available. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` ### Delete site ```http DELETE /sites/{site_id} ``` Delete a site. Careful — you can't undo this, and neither can we. **Permissions:** Requires full account access (`*`). **Returns:** Returns a deleted object on success. Otherwise, this call returns an error. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` **Example request** ```bash curl -X DELETE "https://api.usefathom.com/v1/sites/CDBUGS" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "GCDFS", "object": "site", "deleted": true } ``` --- ## Events Create and manage events (goals) for a site. ### List events ```http GET /sites/{site_id}/events ``` Return a list of all events this site owns. Events are sorted by `created_at` ascending to allow you to paginate with ease. **Permissions:** Requires read access to the site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** A list of event objects. > The `currency` field is only populated on Create and Update responses; it is returned as `null` on list and get responses. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `limit` (integer, query, optional) — A limit on the number of objects to be returned, between 1 and 100. Default: `10`. - `starting_after` (string, query, optional) — A cursor for use in pagination. `starting_after` is an object ID that defines your place in the list. For example, if you make a list request and receive 10 objects ending with `obj_foo`, your subsequent call can include `starting_after=obj_foo` to fetch the next page. - `ending_before` (string, query, optional) — A cursor for use in pagination, working in the opposite direction to `starting_after`. `ending_before` is an object ID that defines your place in the list. **Example request** ```bash curl "https://api.usefathom.com/v1/sites/CDBUGS/events" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "object": "list", "url": "/v1/sites/CDBUGS/events", "has_more": false, "data": [ { "id": "ABCDEFGH", "object": "event", "name": "Signed up to newsletter", "currency": null, "created_at": "2020-08-21 15:24:00" }, { "id": "IJKLMNOP", "object": "event", "name": "Purchased product", "currency": null, "created_at": "2020-08-21 15:24:00" } ] } ``` ### Get event ```http GET /sites/{site_id}/events/{event_id} ``` Return a single event. **Permissions:** Requires read access to the site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** An event object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `event_id` (string, path, required) — The `id` (tracking code) of the event, as returned when the event was created. Example: `ABCDEFGH` **Example request** ```bash curl "https://api.usefathom.com/v1/sites/CDBUGS/events/ABCDEFGH" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "ABCDEFGH", "object": "event", "name": "Signed up to newsletter", "currency": null, "created_at": "2020-08-21 15:24:00" } ``` ### Create event ```http POST /sites/{site_id}/events ``` Create an event. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** An event object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `name` (string, body, required) — The name of the event (up to 255 characters). Example: `Purchase early access` - `currency` (string, body, optional) — The currency used for any value attached to this event's completions. If omitted, defaults to `dollar`. One of: `dollar`, `pound`, `euro`, `yuan`, `peso`, `shekel`, `yen`, `won`, `hryvnia`, `franc`, `rupee`, `integer`, `none`. Default: `dollar`. **Example request** ```bash curl -X POST "https://api.usefathom.com/v1/sites/CDBUGS/events" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "Purchase early access" }' ``` **Example response (`200`)** ```json { "id": "ABCDEFGH", "object": "event", "name": "Purchase early access", "currency": "dollar", "created_at": "2021-08-10 10:45:43" } ``` ### Update event ```http POST /sites/{site_id}/events/{event_id} ``` Update an event. Send only the fields you want to change. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** An event object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `event_id` (string, path, required) — The `id` (tracking code) of the event you wish to update. Example: `ABCDEFGH` - `name` (string, body, optional) — The name of the event (up to 255 characters). - `currency` (string, body, optional) — The currency used for any value attached to this event's completions. One of: `dollar`, `pound`, `euro`, `yuan`, `peso`, `shekel`, `yen`, `won`, `hryvnia`, `franc`, `rupee`, `integer`, `none`. **Example request** ```bash curl -X POST "https://api.usefathom.com/v1/sites/CDBUGS/events/ABCDEFGH" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "ABCDEFGH", "object": "event", "name": "Purchase early access (live)", "currency": "dollar", "created_at": "2021-08-10 10:45:43" } ``` ### Wipe event ```http DELETE /sites/{site_id}/events/{event_id}/data ``` > **Deprecated.** This endpoint has been retired and now returns `410 Gone`. It is no longer possible to wipe an event's completion data via the API. Previously wiped all completion data belonging to an event. This endpoint is no longer available. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `event_id` (string, path, required) — The `id` (tracking code) of the event. ### Delete event ```http DELETE /sites/{site_id}/events/{event_id} ``` Delete an event. Careful — you can't undo this, and neither can we. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** Returns a deleted object on success. Otherwise, this call returns an error. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `event_id` (string, path, required) — The `id` (tracking code) of the event you wish to delete. **Example request** ```bash curl -X DELETE "https://api.usefathom.com/v1/sites/CDBUGS/events/ABCDEFGH" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "ABCDEFGH", "object": "event", "deleted": true } ``` --- ## Milestones Annotate your reports with important dates. ### List milestones ```http GET /sites/{site_id}/milestones ``` Return a list of all milestones this site owns. Milestones are sorted by `created_at` ascending to allow you to paginate with ease. **Permissions:** Requires read access to the site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** A list of milestone objects. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `limit` (integer, query, optional) — A limit on the number of objects to be returned, between 1 and 100. Default: `10`. - `starting_after` (string, query, optional) — A cursor for use in pagination. `starting_after` is an object ID that defines your place in the list. For example, if you make a list request and receive 10 objects ending with `obj_foo`, your subsequent call can include `starting_after=obj_foo` to fetch the next page. - `ending_before` (string, query, optional) — A cursor for use in pagination, working in the opposite direction to `starting_after`. `ending_before` is an object ID that defines your place in the list. **Example request** ```bash curl "https://api.usefathom.com/v1/sites/CDBUGS/milestones" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "object": "list", "url": "/api/v1/CDBUGS/milestones", "has_more": false, "data": [ { "id": "ddc9cdff-ab83-41fa-96c6-dfb276a862e7", "object": "milestone", "name": "Website Redesign Launch", "milestone_date": "2024-01-15 00:00:00", "created_at": "2024-01-10 12:00:00", "updated_at": "2024-01-10 12:00:00" }, { "id": "7c3a1b29-5d64-4e0a-b1f2-9a8c7e6d5f43", "object": "milestone", "name": "Marketing Campaign Start", "milestone_date": "2024-02-01 00:00:00", "created_at": "2024-01-20 09:30:00", "updated_at": "2024-01-20 09:30:00" } ] } ``` ### Get milestone ```http GET /sites/{site_id}/milestones/{milestone_id} ``` Return a single milestone. **Permissions:** Requires read access to the site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** A milestone object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `milestone_id` (string, path, required) — The `id` (UUID) of the milestone you wish to retrieve. **Example request** ```bash curl "https://api.usefathom.com/v1/sites/CDBUGS/milestones/ddc9cdff-ab83-41fa-96c6-dfb276a862e7" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "ddc9cdff-ab83-41fa-96c6-dfb276a862e7", "object": "milestone", "name": "Website Redesign Launch", "milestone_date": "2024-01-15 00:00:00", "created_at": "2024-01-10 12:00:00", "updated_at": "2024-01-10 12:00:00" } ``` ### Create milestone ```http POST /sites/{site_id}/milestones ``` Create a milestone. Returns HTTP `201 Created` on success. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** A milestone object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `name` (string, body, required) — The name of the milestone (up to 30 characters). - `milestone_date` (string, body, required) — The date of the milestone in `YYYY-MM-DD` format. **Example request** ```bash curl -X POST "https://api.usefathom.com/v1/sites/CDBUGS/milestones" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "Website Redesign Launch", "milestone_date": "2024-01-15" }' ``` **Example response (`201`)** ```json { "id": "ddc9cdff-ab83-41fa-96c6-dfb276a862e7", "object": "milestone", "name": "Website Redesign Launch", "milestone_date": "2024-01-15 00:00:00", "created_at": "2024-01-10 12:00:00", "updated_at": "2024-01-10 12:00:00" } ``` ### Update milestone ```http POST /sites/{site_id}/milestones/{milestone_id} ``` Update a milestone. Both `name` and `milestone_date` are required. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** A milestone object. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `milestone_id` (string, path, required) — The `id` (UUID) of the milestone you wish to update. - `name` (string, body, required) — The name of the milestone (up to 30 characters). - `milestone_date` (string, body, required) — The date of the milestone in `YYYY-MM-DD` format. **Example request** ```bash curl -X POST "https://api.usefathom.com/v1/sites/CDBUGS/milestones/ddc9cdff-ab83-41fa-96c6-dfb276a862e7" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "Website Redesign Launch v2", "milestone_date": "2024-01-20" }' ``` **Example response (`200`)** ```json { "id": "ddc9cdff-ab83-41fa-96c6-dfb276a862e7", "object": "milestone", "name": "Website Redesign Launch v2", "milestone_date": "2024-01-20 00:00:00", "created_at": "2024-01-10 12:00:00", "updated_at": "2024-01-10 12:30:00" } ``` ### Delete milestone ```http DELETE /sites/{site_id}/milestones/{milestone_id} ``` Delete a milestone. Careful — you can't undo this, and neither can we. **Permissions:** Requires write access to the site (`manage:{site_id}`). **Returns:** Returns a deleted object on success. Otherwise, this call returns an error. **Parameters** - `site_id` (string, path, required) — The ID of the site. This is the same string you use in your tracking code. Example: `CDBUGS` - `milestone_id` (string, path, required) — The `id` (UUID) of the milestone you wish to delete. **Example request** ```bash curl -X DELETE "https://api.usefathom.com/v1/sites/CDBUGS/milestones/ddc9cdff-ab83-41fa-96c6-dfb276a862e7" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json { "id": "ddc9cdff-ab83-41fa-96c6-dfb276a862e7", "object": "milestone", "deleted": true } ``` --- ## Reports Generate flexible, ad-hoc reports across your data. ### Aggregation ```http GET /aggregations ``` Generate an aggregation. This is an incredibly flexible report that allows you to group on any fields you wish, and filter them at your leisure. **Permissions:** Requires read access to the relevant site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** Returns an array of objects. The properties of each object vary based on the aggregates and groupings you've asked for. All numeric values are returned as strings. > This API endpoint is only accurate on data from March 2021 onwards. Before then, we did not tie browser, country, pathname, etc. together, so we have no way to offer this advanced filtering on that data. **Parameters** - `entity` (string, query, required) — The entity you want to report on. Events are treated separately from pageviews. Supported values: `pageview` and `event`. One of: `pageview`, `event`. - `entity_id` (string, query, Required when entity is "pageview") — When `entity` is `pageview`, this is the `id` of the site you want to aggregate on. When `entity` is `event`, you may instead pass the event's tracking code here. **Tip:** for events, we recommend using `site_id` + `entity_name` instead of an event tracking code. - `site_id` (string, query, Required when entity is "event" and entity_id is omitted) — The `id` of the site the event belongs to. - `entity_name` (string, query, Required when entity is "event" and entity_id is omitted) — The name of the event you want to report on. Example: `purchase`. - `aggregates` (string, query, required) — The aggregates you wish to include, separated by a comma. Supported values for **pageview** entities: `visits`, `uniques`, `pageviews`, `avg_duration` and `bounce_rate`. The difference between "visits" and "uniques" is that visits are unique site visits whilst uniques are unique page visits. Supported values for **event** entities: `conversions`, `unique_conversions` and `value` (value is returned in cents). - `date_grouping` (string, query, optional) — By default, we don't do any date grouping and return total aggregations. Override this with `hour`, `day`, `month` or `year`. Note: `hour` grouping is only supported for date ranges of up to 7 days. One of: `hour`, `day`, `month`, `year`. - `field_grouping` (string, query, optional) — The fields you want to group by, separated by a comma (e.g. `hostname,pathname`). Supported values: `hostname`, `pathname`, `referrer_hostname`, `referrer_pathname`, `referrer_source`, `browser`, `country_code`, `city`, `state`, `region`, `device_type`, `operating_system`, `utm_campaign`, `utm_content`, `utm_medium`, `utm_source`, `utm_term`, `keyword` and `ref`. - `sort_by` (string, query, optional) — The field you want to sort by, in the format `field:asc|desc`. You can use any field present in `aggregates` or `field_grouping`. When using `date_grouping`, you can also sort by `timestamp:asc` or `timestamp:desc`. Example: `pageviews:desc` - `date_from` (string, query, optional) — Timestamp (e.g. `2022-04-01 15:31:00`). Should match the timezone you're reporting in. Defaults to the entity's first recorded data. - `date_to` (string, query, optional) — Timestamp (e.g. `2022-04-01 15:31:00`). Should match the timezone you're reporting in. Default: now. - `timezone` (string, query, optional) — **Deprecated.** We now report using each site's configured timezone by default. If provided, this [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) overrides the site's timezone for this request. We'll be removing this parameter in the future. - `limit` (integer, query, optional) — A limit on the number of rows returned. If you group by a high-cardinality field (e.g. `pathname`), you should set a limit to keep responses fast. - `filters` (array, query, optional) — A JSON-encoded array of filter objects. See the filtering reference below for the full list of supported properties and operators. Each filter's `value` must be a string. #### Filtering Filters are supplied as a JSON array. Each filter is an object with a `property`, an `operator` and a string `value`. You can add as many filters as you like; see the examples in the code panel. We support the following operators: - `is` — exact match - `is not` — everything except an exact match - `is like` — contains the term (supports wildcards `*`) - `is not like` — does not contain the term - `matching` — matches a regular expression (regex) pattern - `not matching` — does not match a regex pattern **Operator availability depends on the field.** Text-style fields support all six operators; categorical fields support only `is` and `is not`: - **All six operators:** `domain`, `hostname`, `pathname`, `referrer_hostname`, `referrer_pathname`, `referrer_source`, `ref`, `utm_campaign`, `utm_source`, `utm_medium`, `utm_content`, `utm_term` - **`is` / `is not` only:** `device_type`, `operating_system`, `browser`, `country_code`, `city`, `state`, `region` Note: `domain` can be filtered on but not grouped by, while `keyword` can be grouped by but not filtered on. ##### Regex examples With `matching` / `not matching` you can build sophisticated filters: - `^/(about|contact|pricing)$` — match only /about, /contact and /pricing - `^/(about|contact|pricing)` — match paths starting with those - `^/blog/\d{4}/\d{2}/` — match blog URLs like /blog/2025/07/my-post - `^/products/[^/]+/$` — match product category pages **Example request** ```bash curl "https://api.usefathom.com/v1/aggregations?entity=pageview&aggregates=pageviews" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response (`200`)** ```json [ { "browser": "Chrome", "device_type": "Desktop", "pageviews": "30000" }, { "browser": "Chrome", "device_type": "Mobile", "pageviews": "28000" }, { "browser": "Chrome", "device_type": "Tablet", "pageviews": "24000" }, { "browser": "Firefox", "device_type": "Desktop", "pageviews": "12000" }, { "browser": "Firefox", "device_type": "Tablet", "pageviews": "5000" }, { "browser": "Firefox", "device_type": "Mobile", "pageviews": "300" } ] ``` **Example response — Filter: only include the /about page (`200`)** ```json [ { "property": "pathname", "operator": "is", "value": "/about" } ] ``` **Example response — Filter: exclude /register and /login (`200`)** ```json [ { "property": "pathname", "operator": "is not", "value": "/register" }, { "property": "pathname", "operator": "is not", "value": "/login" } ] ``` **Example response — Filter: only include the United Kingdom (`200`)** ```json [ { "property": "country_code", "operator": "is", "value": "GB" } ] ``` **Example response — Filter: exclude /register or Desktop (`200`)** ```json [ { "property": "pathname", "operator": "is not", "value": "/register" }, { "property": "device_type", "operator": "is not", "value": "Desktop" } ] ``` ### Current visitors ```http GET /current_visitors ``` Returns the total number of current visitors on a site. The detailed view also returns the top 150 pages and top 150 referrers. **Permissions:** Requires read access to the site (`all-sites-readonly`, `read:{site_id}` or `manage:{site_id}`). **Returns:** The current visitor count, with an optional detailed breakdown. **Parameters** - `site_id` (string, query, required) — The `id` of the site. Example: `CDBUGS` - `detailed` (boolean, query, optional) — Set to `true` for a detailed breakdown of pages and referrers. Otherwise you'll only get a count. Default: `false`. **Example request** ```bash curl "https://api.usefathom.com/v1/current_visitors?site_id=CDBUGS" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json" ``` **Example response — Simple (`200`)** ```json { "total": 14 } ``` **Example response — Detailed (`200`)** ```json { "total": 144, "content": [ { "hostname": "bugsbunny.com", "pathname": "/spacejam", "total": 100 }, { "hostname": "bugsbunny.com", "pathname": "/blog/being-a-wabbit", "total": 44 } ], "referrers": [ { "referrer_hostname": "https://usefathom.com", "referrer_pathname": "/why-we-love-bugs-bunny", "total": 50 }, { "referrer_hostname": "https://daffyduck.com", "referrer_pathname": "/blog/i-am-sick-of-his-antics", "total": 32 } ] } ```