---
url: /api/docs/geofeeds.md
---
# Geofeeds

Host and manage your geofeeds, and monitor whether geolocation providers are using them.

## Background

A geofeed is a self-published CSV file that tells geolocation providers where your IP prefixes are located. Its format is defined in [RFC 8805](https://www.rfc-editor.org/rfc/rfc8805).

RFC 8805 does not say how providers should find your geofeed. That is the purpose of [RFC9092](https://www.rfc-editor.org/rfc/rfc9092)/[RFC9632](https://www.rfc-editor.org/rfc/rfc9632) ("Finding and Using Geofeed Data", where RFC9632 updates RFC9092). They define how to reference a geofeed from Regional Internet Registries (RIR) databases: you add the geofeed URL to the `inetnum` (IPv4) or `inet6num` (IPv6) object covering the prefixes (in ARIN, `NetRange`), using the `geofeed:` attribute, or, where the registry does not support it, a `remarks: Geofeed <URL>` line. Geolocation providers read the registry objects, download the file, and use its data. Only the registry holder of the address block can publish this reference, so it also acts as proof of authority over the data.

Doing this by hand means writing a valid CSV, hosting it on a stable HTTPS URL, keeping it up to date, editing the registry object, and then waiting to see whether providers actually pick up the data. This API automates those steps:

* **Hosting and generation:** you send your entries as JSON (see [Create or update geofeeds](#create-or-update-geofeeds)). PacketVis validates and corrects them, and publishes a valid RFC 8805 file, so you don't maintain the CSV or a web server. The `url` of each entry is the value to reference in the registry object.
* **Installation check:** [monitoring](#monitor-a-prefix) verifies that the geofeed is correctly referenced in the registry database, that the file is reachable, and that its content is valid.
* **Provider monitoring:** the monitoring endpoints also compare what each geolocation provider reports with your geofeed and flag mismatches, so you can verify that the installation works end to end.
* **Automation:** since everything is available through the API, you can update geofeeds from your own provisioning systems and check the result, with no manual file editing.

## Getting started

1. [Generate an API key](https://packetvis.com/settings/apikeys) (see [Authentication](/docs/authentication)).
2. Build the request URL for the endpoint you need. Replace `YOUR_API_KEY` in the examples with your API key.

Example prefixes use the documentation-only ranges defined in [RFC 5737](https://www.rfc-editor.org/rfc/rfc5737), and example URLs use the reserved `example.com` domain.

## List geofeeds

Returns the geofeeds currently managed by PacketVis.

### Parameters

| Name  | Description  | Default |
|-------|--------------|---------|
| `key` | The API key. |         |

### Response

200 OK

```json
{
  "data": [
    {
      "prefix": "203.0.113.0/25",
      "country": "JP",
      "city": null,
      "region": null,
      "zip": null,
      "group": "customer1",
      "lastGeolocationChange": "2026-10-20T11:58:04.390Z",
      "inetnum": "203.0.113.0-203.0.113.255",
      "createdAt": "2026-10-20T11:58:04.391Z",
      "updatedAt": "2026-10-20T11:58:04.391Z",
      "url": "https://geofeeds.example.com/geofeed.csv"
    },
    {
      "prefix": "203.0.113.128/28",
      "country": "JP",
      "city": "Tokyo",
      "region": "JP-13",
      "zip": null,
      "group": "customer1",
      "lastGeolocationChange": "2026-10-20T11:58:04.500Z",
      "inetnum": "203.0.113.0-203.0.113.255",
      "createdAt": "2026-10-20T11:58:04.500Z",
      "updatedAt": "2026-10-20T11:58:04.500Z",
      "url": "https://geofeeds.example.com/geofeed.csv"
    }
  ],
  "metadata": {}
}
```

Each object in `data` is a geofeed entry:

| Field | Type | Description |
|-------|------|-------------|
| `prefix` | string | IP prefix in CIDR notation the entry applies to. |
| `country` | string | null | ISO 3166-1 alpha-2 country code. |
| `region` | string | null | ISO 3166-2 region code (e.g., `JP-13`). |
| `city` | string | null | City name. |
| `zip` | string | null | Postal code. |
| `group` | string | null | Optional label used to group entries (e.g., by customer). |
| `lastGeolocationChange` | string (ISO 8601) | When the geographic information of the entry last changed. |
| `inetnum` | string | Address range of the registry object where the geofeed is referenced. |
| `createdAt` | string (ISO 8601) | When the entry was created. |
| `updatedAt` | string (ISO 8601) | When the entry was last updated. |
| `url` | string | URL of the hosted geofeed file containing the entry. |

## Create or update geofeeds

Creates or modifies the geofeeds hosted by PacketVis.

### Parameters

| Name  | Description                                                |  Default |
|-------|------------------------------------------------------------|----------|
| `key` | The API key. It must have write access.                    |          |

### Request body

```json
{
  "data": [
    {
      "prefix": "203.0.113.0/25",
      "country": "JP",
      "region": "JP-13",
      "city": "Tokyo",
      "zip": null,
      "group": "customer1"
    },
    {
      "prefix": "203.0.113.128/28",
      "country": "JP",
      "region": "JP-27",
      "city": "Osaa",
      "zip": null,
      "group": null
    }
  ]
}
```

Each entry follows the geofeed format defined in [RFC 8805](https://www.rfc-editor.org/rfc/rfc8805), with the addition of the `group` attribute:

| Field | Required | Type | Description |
|-------|----------|------|-------------|
| `prefix` | yes | string | IPv4 or IPv6 prefix in CIDR notation. |
| `country` | yes | string | null | ISO 3166-1 alpha-2 country code. |
| `region` | no | string | null | ISO 3166-2 subdivision code (e.g., `JP-13`). |
| `city` | no | string | null | City name. |
| `zip` | no | string | null | Postal code. |
| `group` | no | string | null | Free-form label identifying a group of geofeeds, e.g., a customer. It allows group operations, such as deleting all the geofeeds of a given customer. |

Per RFC 8805, if `country`, `region`, `city`, and `zip` are all `null`, the prefix is explicitly marked as not to be geolocated.

Note the misspelled city in the last entry: "Osaa" instead of "Osaka". It is intentional, and the response below shows how it is handled.

### Response

200 OK

```json
[
  {
    "group": "customer1",
    "geofeed": {
      "prefix": "203.0.113.0/25",
      "country": "JP",
      "region": "JP-13",
      "city": "Tokyo",
      "zip": null
    },
    "error": null,
    "cleaned": {
      "prefix": "203.0.113.0/25",
      "country": "JP",
      "region": "JP-13",
      "city": "Tokyo",
      "zip": null
    }
  },
  {
    "group": null,
    "geofeed": {
      "prefix": "203.0.113.128/28",
      "country": "JP",
      "region": "JP-27",
      "city": "Osaa",
      "zip": null
    },
    "error": "Error: We cannot find the city for the country",
    "cleaned": {
      "prefix": "203.0.113.128/28",
      "country": "JP",
      "region": "JP-27",
      "city": null,
      "zip": null
    }
  }
]
```

The response contains both the entry you submitted and the cleaned version that was actually applied. It is an array with one object per submitted entry:

| Field | Type | Description |
|-------|------|-------------|
| `group` | string | null | The group the entry was submitted with. |
| `geofeed` | object | The entry exactly as submitted (`prefix`, `country`, `region`, `city`, `zip`). |
| `error` | string | null | Description of the problem that required the entry to be adapted, or `null` if the entry was accepted as is. |
| `cleaned` | object | The entry as actually applied, after the corrections. Same attributes as `geofeed`. |

In the last entry, the system could not find the city "Osaa" for the given country, so it reported an error and set the city to `null`. You can then correct the city and submit the geofeed again.

## Monitor a prefix

Enables geolocation monitoring for the prefix and returns the current geolocation data of each provider.

### What is monitored

Monitoring checks the whole chain, from the registry database to the geolocation providers:

1. **Installation in the RIR database:** the `inetnum`/`inet6num`/`NetRange` object covering the prefix must reference the geofeed, with the `geofeed:` attribute or a `remarks: Geofeed <URL>` line, as defined in [RFC9092](https://www.rfc-editor.org/rfc/rfc9092)/[RFC9632](https://www.rfc-editor.org/rfc/rfc9632). A missing, malformed, or misplaced reference means the providers cannot find your geofeed. The URL found is reported in `file`.
2. **Reachability of the file:** the URL referenced in the registry object must be reachable over the network, so that the providers can download it.
3. **Correctness of the file:** the downloaded file must be valid according to [RFC 8805](https://www.rfc-editor.org/rfc/rfc8805), and must contain an entry for the monitored prefix, with the geographic information you expect.
4. **Provider data:** the geolocation data returned by each provider is compared with the geofeed. `countrySync` and `citySync` tell you whether each provider is aligned.

Problems in steps 1 to 3 prevent providers from using your geofeed. A mismatch in the provider data is often a consequence.

If the email corrections service is enabled, this endpoint also shows when emails are sent to the geolocation providers (`emailCount` and `lastEmail`). Emails are sent only to providers that do not comply with [RFC9092](https://www.rfc-editor.org/rfc/rfc9092)/[RFC9632](https://www.rfc-editor.org/rfc/rfc9632) for a specific prefix even though the installation is correct.

### Parameters

| Name     | Description                                      | Default |
|----------|--------------------------------------------------|---------|
| `key`    | The API key.                                     |         |
| `prefix` | The prefix to monitor, in the URL path (CIDR).   |         |

### Response

200 OK

```json
{
  "data": [
    {
      "prefix": "198.51.100.0/24",
      "country": "ES",
      "region": "ES-VC",
      "city": "Torrevieja",
      "zip": null,
      "file": "https://geofeeds.example.com/geofeed.csv",
      "active": true,
      "countrySync": true,
      "citySync": false,
      "emailCount": 3,
      "lastEmail": "2026-09-17T14:08:51.936Z",
      "createdAt": "2026-09-15T13:05:44.825Z",
      "updatedAt": "2026-10-22T13:34:56.576Z",
      "provider": "Geolocation Provider 1"
    },
    {
      "prefix": "198.51.100.0/24",
      "country": "ES",
      "region": null,
      "city": "Alicante",
      "zip": null,
      "file": "https://geofeeds.example.com/geofeed.csv",
      "active": true,
      "countrySync": true,
      "citySync": true,
      "emailCount": 0,
      "lastEmail": null,
      "createdAt": "2026-09-15T13:05:44.825Z",
      "updatedAt": "2026-10-22T13:34:56.576Z",
      "provider": "Geolocation Provider 2"
    },
      ...
  ],
  "metadata": {}
}
```

Each entry is the current geolocation information retrieved from one geolocation provider:

| Field | Type | Description |
|-------|------|-------------|
| `prefix` | string | The monitored prefix. |
| `country` | string | null | Country code reported by the provider. |
| `region` | string | null | Region code reported by the provider. |
| `city` | string | null | City reported by the provider. |
| `zip` | string | null | Postal code reported by the provider. |
| `file` | string | URL of the geofeed file that the providers are expected to read. |
| `active` | boolean | Whether the monitoring of this prefix is active. |
| `countrySync` | boolean | `true` if the provider's country matches the geofeed. |
| `citySync` | boolean | `true` if the provider's city matches the geofeed. |
| `emailCount` | integer | Number of notification emails sent to the provider about this mismatch. |
| `lastEmail` | string (ISO 8601) | null | When the last email was sent to the provider. |
| `createdAt` | string (ISO 8601) | When the monitoring was enabled. |
| `updatedAt` | string (ISO 8601) | When the provider data was last refreshed. |
| `provider` | string | Name of the geolocation provider. |

Each request triggers a new check with all geolocation providers. A given provider is checked at most once every 24 hours: if the last check was less than 24 hours ago, no new check is triggered.

## Overall Geolocation status

This endpoint allows you to keep under control the geolocation of all your IP resources in one go. It reports both the geofeeds hosted by PacketVis and those hosted elsewhere for which you requested monitoring.

### Parameters

| Name  | Description  | Default |
|-------|--------------|---------|
| `key` | The API key. |         |

### Response

200 OK

```json
{
  "data": [
    {
      "monitored": true,
      "results": [
        {
          "country": "US",
          "region": null,
          "city": "Boca Raton",
          "zip": null,
          "active": true,
          "countrySync": true,
          "citySync": true,
          "updatedAt": "2026-09-14T10:06:44.195Z",
          "provider": "Geolocation Provider 1"
        },
        {
          "country": "US",
          "region": "US-FL",
          "city": "Miami",
          "zip": null,
          "active": true,
          "countrySync": true,
          "citySync": false,
          "updatedAt": "2026-09-14T10:06:44.195Z",
          "provider": "Geolocation Provider 2"
        },
          ...
      ],
      "city": "Boca Ratón",
      "country": "US",
      "region": "US-FL",
      "prefix": "192.0.2.0/24",
      "group": null,
      "lastGeolocationChange": null,
      "providersDataStatus": "outdated",
      "countrySyncErrorPercentage": 0,
      "citySyncErrorPercentage": 50,
      "lastProvidersCheck": "2026-09-14T10:06:44.195Z",
      "file": "https://geofeeds.example.com/geofeed.csv"
    },
    {
      "monitored": false,
      "results": [],
      "city": "Tokyo",
      "country": "JP",
      "region": "JP-13",
      "prefix": "203.0.113.0/25",
      "group": null,
      "lastGeolocationChange": "2026-10-20T11:58:04.390Z",
      "providersDataStatus": "not-checked",
      "citySyncErrorPercentage": null,
      "lastProvidersCheck": null,
      "file": null
    }
  ],
  "metadata": {}
}
```

Fields of each object in `data`:

| Field | Type | Description |
|-------|------|-------------|
| `monitored` | boolean | Whether geolocation monitoring is enabled for the prefix. |
| `results` | array | Latest geolocation data per provider. Empty if the prefix is not monitored. |
| `prefix` | string | The prefix. |
| `country` | string | null | Country in the geofeed. |
| `region` | string | null | Region in the geofeed. |
| `city` | string | null | City in the geofeed. |
| `group` | string | null | Group label of the entry. |
| `lastGeolocationChange` | string (ISO 8601) | null | When the geographic information last changed. |
| `providersDataStatus` | string | Overall status of the data from the providers: `not-checked`, `outdated`, `partially-synced`, or `synced`. |
| `countrySyncErrorPercentage` | number | null | Percentage of providers whose country does not match the geofeed. |
| `citySyncErrorPercentage` | number | null | Percentage of providers whose city does not match the geofeed. |
| `lastProvidersCheck` | string (ISO 8601) | null | When the providers were last checked. |
| `file` | string | null | The geofeed file referenced in the `inetnum` object when correctly installed, i.e., the same file seen by the geolocation providers. |

Each object in `results` contains the same fields as in the monitoring response returned by the [previous endpoint](#monitor-a-prefix) (`country`, `region`, `city`, `zip`, `active`, `countrySync`, `citySync`, `updatedAt`, and `provider`), except `prefix`, `file`, `emailCount`, `lastEmail`, and `createdAt`.

### Provider data status

The `providersDataStatus` field can have the following values:

| Value | Meaning |
|-------|---------|
| `not-checked` | The providers have not been checked yet. |
| `propagating` | The geofeed has been recently updated, and the changes may still be propagating to the providers. |
| `outdated` | The data collected from the providers is outdated. Run a new check to refresh the synchronization status. |
| `not-synced` | None of the providers match the geofeed data. |
| `partially-synced` | Some providers match the geofeed data, while others do not. |
| `synced` | All providers match the geofeed data. |

### Monitored vs. not monitored

* `monitored: true`: monitoring is enabled for the prefix (see [Monitor a prefix](#monitor-a-prefix)). The entry includes the result of the last check with the geolocation providers: `results`, the error percentages, `lastProvidersCheck`, and `file`.
* `monitored: false`: the entry only reports the current geofeed installation. No provider has been checked, so `results` is empty, `providersDataStatus` is `not-checked`, and the sync percentages, `lastProvidersCheck`, and `file` are `null`.

## Geolocation status of a single prefix

This endpoint is identical to [Overall Geolocation status](#overall-geolocation-status), but it returns only the prefix specified in the URL.

### Parameters

| Name     | Description                                    | Default |
|----------|------------------------------------------------|---------|
| `key`    | The API key.                                   |         |
| `prefix` | The prefix to look up, in the URL path (CIDR). |         |

### Response

The response has the same format as the [overall geolocation status](#overall-geolocation-status) endpoint, with `data` containing only the entry of the requested prefix. See the previous section for the description of the fields.

## Delete a geofeed

Removes a prefix from PacketVis. The effect depends on how the prefix is managed:

* **Hosted by PacketVis:** the geofeed entry is deleted and no longer published in the hosted file. Any monitoring of the prefix is also stopped.
* **Monitored only:** the geofeed is hosted elsewhere, so nothing is deleted. PacketVis simply stops monitoring the prefix.

### Parameters

| Name     | Description                                                    | Default |
|----------|----------------------------------------------------------------|---------|
| `key`    | The API key. It must have write access.                        |         |
| `prefix` | The prefix to delete, in the URL path (CIDR).                  |         |

### Response

200 OK

The file is deleted (if hosted by PacketVis) and monitoring is stopped. The response body is empty.
