Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/hubble-network:hubble-network-packets-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Hubble Platform Packets API
description: 'The Hubble platform is built API-first. Use our Cloud API to manage your devices
and access device data programmatically. We''ve designed our API following RESTful principles. Each endpoint returns standard HTTP status codes and may include JSON payloads. ---
## API Access
Use API Keys to authenticate with the Hubble Cloud API for your organization. ### Generate an API Key
Log in to your Hubble dashboard. Navigate to **Developer Tools > API Tokens** to create a new API Key. Provide a name for the token, and set an appropriate expiration date for temporary access. ### Organization ID
You will need `org_id` to make API requests. From your Hubble dashboard, navigate to
**Developer Tooks > API Tokens**, or **Organization Settings**, to find your Organization ID. ### Authorization Scopes
API endpoints require specific authorization scopes to perform the intended operation. **Required Scope** is always provided in the API documentation. API Keys can be created with specific authorization scopes that control what operations the key can perform. If no scopes are specified, the key will be created with all available scopes (admin-level access). | **Scope** | **Access** |
|------------------------------|-------------------------------------------------|
| **read-api-keys** | View API keys and their metadata |
| **write-api-keys** | Create, update, and delete API keys |
| **read-users** | View user information and roles |
| **write-users** | Add, update, and remove users from the organization |
| **read-organization-metadata** | View organization details and settings |
| **write-organization-metadata** | Update organization information |
| **read-devices** | View device information and status |
| **write-devices** | Register and manage devices |
| **read-invitations** | View pending invitations |
| **write-invitations** | Create and revoke user invitations |
| **read-packets** | Access packet data and retrieval endpoints |
| **read-platform-metrics** | View platform metrics and analytics |
| **read-billing-usage** | View billing usage information |
| **read-billing-invoices** | View billing invoices |
| **read-webhooks** | View webhook configurations |
| **write-webhooks** | Create and manage webhook endpoints |
| **read-satellites** | View satellite ephemeris and pass data |
**Example Scope Combinations**
- Create a key with read-only access: `["read-api-keys", "read-users", "read-devices"]`
- Create a key for device management: `["read-devices", "write-devices"]`
- Create a key for user management: `["read-users", "write-users", "read-invitations", "write-invitations"]`
**Best Practices for Data Security**
- Create keys with the minimum required scopes for your use case
- Regularly review and rotate API keys
- Use descriptive names for your keys to track their purpose
- Set appropriate expiration dates for temporary access
---
## Import API Definition
You can quickly import the Hubble Cloud API into your preferred developer environment (such as Postman or Insomnia) using our **public OpenAPI definition**. Simply download or import the YAML file directly:
https://hubble.com/docs/openapi.yaml
---
## Pagination
When the number of objects requested exceeds the maximum page size for an endpoint, the API response will be paginated. This means you will receive a subset of the total results, along with a `Continuation-Token` in the Response Header that can be used to fetch subsequent subsets. To retrieve the next set of data, you must use the provided `Continuation-Token` in the Request Header of your next API call to the same endpoint. Continue using the provided token in each successive request until no `Continuation-Token` is returned, which indicates you have retrieved all available data. ---
## Rate Limits
The Hubble Cloud API follows a leaky bucket approach to rate limiting. Endpoints are rate limited to three (3) requests per second. Your organization is limited to a total of 15 requests per second.'
version: 1.0.0
servers:
- url: https://api.hubble.com
description: Production
security:
- BearerAuth: []
tags:
- name: Packets
paths:
/v1/org/{org_id}/packets:
get:
tags:
- Packets
operationId: retrieve-organization-packets
x-criticality: high
summary: Retrieve Packets
description: 'Stream or query packets for your organization.
**Required Scope:** `read-packets`
## Overview
This endpoint acts as a data stream. Use the `Continuation-Token` to track your consumer''s position in the stream and ingest incrementally.
Packets are returned in ascending order based on when they were detected by Hubble Network.
## Pagination and Streaming
Use the `Continuation-Token` to capture new packets incrementally.
If provided, all other query parameters are ignored, as the token persists the initial query''s configuration.
### Response Headers
* `Continuation-Token`: an opaque cursor for your position in the stream. The max page size is 1,000 packets.
* If you supplied an `end` time, an empty string indicates you have reached that end time and there is no more data in the requested window.
* If you left `end` open, the token never goes empty, since the stream has no end to reach — it always points at your current position, whether or not new packets are waiting there.
* `Retry-After`: the recommended number of seconds to wait before your next poll request (max value is 300 seconds). This is the signal to watch on an open stream: its presence means you are caught up to the live edge, so treat it as your polling backoff rather than looking for an empty `Continuation-Token`.
## Query Parameters (Initial Request)
When starting a new stream (no `Continuation-Token` exists) or to query for data from a period of time, use these parameters to begin polling:
### Time Period (UTC, in seconds)
* `start` time defaults to 7 days ago when not specified.
* Omit `end` time to leave the stream open and poll for new packets indefinitely.
* Supply an `end` time if your consumer needs a terminating, empty-token stop condition.
:::tip
Granular packet data is available up to **30 days** in the past.
:::
### Device Filtering
* When `device_id` is provided, only packets from that device will be returned.
* Note: you cannot page indefinitely for single-device queries. The stream closes when it reaches current time.
:::warning
Device filtering is provided for troubleshooting. It should not be used for high-volume data retrieval.
:::
---
## Packet Data Definitions (Response)
### Location Object
For **TERRESTRIAL** packets, all `location` fields represent the scanning gateway''s most recent GPS lock:
* `location.timestamp` is the timestamp of the location lock.
* `location.latitude` and `location.longitude` are the location coordinates.
* `location.horizontal_accuracy` and `location.vertical_accuracy` represent accuracy variance in meters.
For **SATELLITE** packets, `location.timestamp` and `device.timestamp` are identical: both represent the time the packet was detected by the satellite.
### Device Object
For **TERRESTRIAL** packets,
* `device.timestamp` is the timestamp when the data packet was detected by the gateway.
* `device.rssi` is the received signal strength measured by the gateway.
### Gateway Object
For **self-provided** packets (packets your organization contributed and is also reading back, i.e. `provider_id == org_id`), the response optionally includes a top-level `gateway` object. These fields describe the **scanning gateway** that received the BLE advertisement.
* `gateway.gateway_id` is the stable gateway UUID issued by Hubble when you register using the Gateway API.
* `gateway.service_id` is the normalized 16-bit service UUID from the scanned BLE advertisement (e.g. `fca6`).
:::note
The `gateway` block is **omitted entirely** for packets sourced from a different organization (e.g. third-party crowdsourced traffic), and is also omitted on self-provided packets when no gateway context was attached at ingest.
:::'
parameters:
- $ref: '#/components/parameters/orgIdPathParam'
- $ref: '#/components/parameters/continuationTokenHeader'
- $ref: '#/components/parameters/startQueryParam'
- $ref: '#/components/parameters/endQueryParam'
- $ref: '#/components/parameters/deviceIdQueryParam'
responses:
'200':
description: A page of packets
headers:
Continuation-Token:
$ref: '#/components/headers/ContinuationTokenHeader'
Retry-After:
$ref: '#/components/headers/RetryAfterHeader'
content:
application/json:
schema:
$ref: '#/components/schemas/packetBatch'
'429':
description: An error when too many requests have been made to retrieve packets
headers:
Continuation-Token:
$ref: '#/components/headers/ContinuationTokenHeader'
Retry-After:
$ref: '#/components/headers/RetryAfterHeader'
content:
application/json:
schema:
$ref: '#/components/schemas/errorResponse'
'400':
$ref: '#/components/responses/ErrorBadRequest'
'500':
$ref: '#/components/responses/ErrorInternalServer'
/v1/org/{org_id}/packets/decode:
post:
tags:
- Packets
operationId: decode-packets
x-criticality: high
summary: Decode Packets
description: 'Synchronously decode and decrypt a small batch of BLE advertisement packets for your organization.
**Required Scope:** `read-packets`
The input advertisements are also forwarded to the asynchronous ingest pipeline (the same
pipeline used by `GET /v1/org/{org_id}/packets`) so that packets are persisted regardless of
the synchronous decode outcome.
Only packets that successfully decode and that belong to the calling organization are
returned in the response. Packets that fail to decode, or that belong to a different
organization, are omitted from the response and are instead handled by the asynchronous
pipeline.
## Limits
* Maximum **25** advertisements per request.'
parameters:
- $ref: '#/components/parameters/orgIdPathParam'
- $ref: '#/components/parameters/contentTypeJsonHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/decodePacketsRequestBody'
responses:
'200':
description: A batch of decoded packets belonging to the calling organization.
content:
application/json:
schema:
$ref: '#/components/schemas/synchronousDecodePacketBatch'
'400':
$ref: '#/components/responses/ErrorBadRequest'
'500':
$ref: '#/components/responses/ErrorInternalServer'
/v1/webhook/testBatch:
post:
tags:
- Packets
operationId: packet-webhook-example
x-criticality: high
summary: Packet Webhook Example
description: 'This endpoint is an example webhook endpoint that each organization can implement in order to receive packet data.
Packet data that has been decrypted for your organization will be forwarded to these webhooks.
### Batching
Packets are sent in batches to minimize HTTP overhead from sending packets individually.
Batch sizes are configurable per webhook endpoint.
The actual number of packets per request will range between 1 and the configured `max_batch_size`.'
parameters:
- $ref: '#/components/parameters/contentTypeJsonHeader'
- $ref: '#/components/parameters/webhookSecretHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/packetBatch'
responses:
'200':
description: Message delivered.
'500':
description: Internal Server Error. Please Retry.
components:
schemas:
deviceId:
type: string
format: uuid
description: Primary UUID identifier for a registered device
deviceName:
type: string
description: Assigned name for the device
maxLength: 250
orgId:
type: string
format: uuid
description: The ID for an organization
gateway:
type: object
description: 'Metadata about the scanning gateway that received this packet — the relay
that detected the BLE advertisement, not the device that emitted it.
Only present on self-provided packets (`provider_id == org_id`) where
gateway context was attached at ingest. Both fields are optional.
'
properties:
gateway_id:
type: string
format: uuid
description: 'Stable unique identifier of the gateway device that received the packet.
This is the gateway UUID issued at registration time and is consistent
across all packets from the same gateway.
'
service_id:
type: string
description: 'Normalized 16-bit BLE service UUID that the advertisement was scanned
under (lowercase hex, e.g. `fca6` for Hubble packets). Identifies which
BLE service profile the gateway matched when it captured this packet.
'
example: fca6
packet:
type: object
properties:
location:
$ref: '#/components/schemas/location'
device:
type: object
required:
- id
- payload
- timestamp
properties:
id:
$ref: '#/components/schemas/deviceId'
name:
$ref: '#/components/schemas/deviceName'
tags:
$ref: '#/components/schemas/deviceTags'
payload:
type: string
description: A packet's decrypted payload in Base64 format
rssi:
type: number
timestamp:
$ref: '#/components/schemas/utcTimestampNumber'
counter:
type: number
description: 'The time-based counter associated with this packet.
'
sequence_number:
type: number
description: 'The sequence number of this packet
'
network_type:
type: string
enum:
- TERRESTRIAL
- SATELLITE
gateway:
$ref: '#/components/schemas/gateway'
utcTimestampInteger:
type: integer
format: int64
description: An UTC second-precision timestamp formatted as an integer
decodePacketsRequestBody:
type: object
required:
- advertisements
properties:
advertisements:
type: array
minItems: 1
maxItems: 25
description: 'A flat list of BLE advertisement packets to decode. Each item carries its own
`location`. Maximum 25 packets per request.
'
items:
type: object
required:
- payload
- rssi
- timestamp
- location
properties:
payload:
type: string
description: Raw BLE advertisement payload in Base64 format.
rssi:
type: number
description: Signal strength in dBm.
timestamp:
$ref: '#/components/schemas/utcTimestampNumber'
location:
$ref: '#/components/schemas/location'
metadata:
allOf:
- $ref: '#/components/schemas/providerMetadata'
description: 'Optional per-advertisement provider/gateway metadata.
'
metadata:
allOf:
- $ref: '#/components/schemas/providerMetadata'
description: 'Optional batch-level provider/gateway metadata
'
synchronousDecodePacketBatch:
type: object
properties:
packets:
type: array
items:
$ref: '#/components/schemas/synchronousDecodePacket'
providerMetadata:
type: object
description: 'Provider/gateway metadata describing the submitting client.
'
properties:
platform:
type: string
description: Free-form platform identifier (e.g. `"android"`, `"ios"`, `"linux"`).
platform_version:
type: string
description: Free-form platform / SDK version string.
os:
type: string
description: Operating system name.
os_version:
type: string
description: Operating system version string.
location:
type: object
required:
- latitude
- longitude
- altitude
- timestamp
properties:
latitude:
type: number
description: Latitude in Decimal Degrees DDD.DDDDD°
longitude:
type: number
description: Longitude in Decimal Degrees DDD.DDDDD°
altitude:
type: number
description: Altitude in meters for the provided gps coordinates
horizontal_accuracy:
type: number
description: Horizontal accuracy in meters for the provided gps coordinates
vertical_accuracy:
type: number
description: Vertical accuracy in meters for the provided gps coordinates
timestamp:
$ref: '#/components/schemas/utcTimestampNumber'
packetBatch:
type: object
properties:
packets:
type: array
items:
$ref: '#/components/schemas/packet'
synchronousDecodePacket:
description: 'A successfully decoded packet returned by `POST /v1/org/{org_id}/packets/decode`.
'
allOf:
- $ref: '#/components/schemas/packet'
- type: object
properties:
advertisement:
type: object
properties:
payload:
type: string
description: 'The Base64-encoded BLE advertisement payload that was submitted for
decoding. Identical to the `payload` field on the corresponding input
advertisement object.
'
deviceTags:
type: object
additionalProperties:
type: string
description: "Tags are user-defined key/value pairs that can be attributed to a device. \nA device may have up to 10 tags.\n**Custom tags:** create your own tags with `key` length up to 32 characters and `value` length up to 128 characters.\n**Platform tags:** use Hubble-defined tags to organize devices.\n- `_env` tag: `production` indicates if a device belongs to the live environment, and `sandbox` for the test environment. A device will always have an `_env` tag assigned.\n"
example:
_env: production
utcTimestampNumber:
type: number
format: double
description: An UTC second-precision timestamp formatted as a floating point number
errorResponse:
type: object
properties:
code:
type: integer
description: The HTTP status code
description:
type: string
description: 'A description for the error.
For user errors, we attempt to be as descriptive as possible to help with diagnosing the issue.
For internal errors, the error description is only indicates that a retry should occur but we log the full error so that we can diagnose it.
Error descriptions can change over time and should not be programmed against.
'
name:
type: string
enum:
- Bad Request
- Unauthorized
- Not Found
- Request Entity Too Large
- Too Many Requests
- Internal Server Error
description: '`name` is a short name for the error.
'
webhookSecret:
type: string
description: 'A confidential, unique string generated for your webhook endpoint to validate that the request came from Hubble.
Hubble will send this token in the HTTP header `HTTP-X-HUBBLE-TOKEN` when making HTTPS requests to your endpoint.
'
headers:
RetryAfterHeader:
description: 'The number of seconds to wait to attempt a retry.
When attached to a 200, this is a suggestion because the most recent data has been retrieved already.
When attached to a 429, this delay is a recommendation to reduce repeat 429s.
'
schema:
type: integer
minimum: 0
maximum: 300
ContinuationTokenHeader:
description: A token to indicate how to continue paging
schema:
type: string
parameters:
orgIdPathParam:
name: org_id
in: path
required: true
schema:
$ref: '#/components/schemas/orgId'
description: Your organization ID
deviceIdQueryParam:
name: device_id
in: query
required: false
schema:
$ref: '#/components/schemas/deviceId'
description: 'Filter packets to a specific device
'
webhookSecretHeader:
name: HTTP-X-HUBBLE-TOKEN
in: header
required: true
schema:
$ref: '#/components/schemas/webhookSecret'
description: 'A confidential, unique string generated for your webhook endpoint to validate that the request came from Hubble.
'
continuationTokenHeader:
name: Continuation-Token
in: header
required: false
schema:
type: string
description: A token to indicate how to continue paging
startQueryParam:
name: start
in: query
required: false
schema:
$ref: '#/components/schemas/utcTimestampInteger'
description: "UTC timestamp (in seconds) indicating when to start retrieving packets. \nThis timestamp corresponds to when the packet was received by the network.\nIf omitted, defaults to 7 days before the current UTC time.\n"
endQueryParam:
name: end
in: query
required: false
schema:
$ref: '#/components/schemas/utcTimestampInteger'
description: 'UTC timestamp (in seconds) indicating when to end retrieving packets.
This timestamp corresponds to when the packet was received by the network.
If omitted, defaults to empty (meaning the pagination will continue indefinitely).
If specified, pagination will continue until all packets received prior to the timestamp have been returned.
'
contentTypeJsonHeader:
name: Content-Type
in: header
schema:
type: string
description: An indication that the payload is JSON
example: application/json
responses:
ErrorBadRequest:
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/errorResponse'
example:
code: 400
description: The request could not be understood by the server due to malformed syntax.
name: Bad Request
ErrorInternalServer:
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/errorResponse'
example:
code: 500
description: An unknown error has occurred.
name: Unknown
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
x-provenance:
method: harvested
publisher: Hubble Network
source: https://hubble.com/docs/openapi.yaml
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)