Work with this as data
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.
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/formo-so:formo-so-events-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 Specification
openapi: 3.2.0
info:
title: Formo Public Events API
description: 'REST API for managing Formo projects, analytics, alerts, boards, charts, contracts, segments, and AI chat.
**Auth.** Every endpoint on `api.formo.so` requires a workspace API key with the appropriate scopes (see `x-api-scopes`). The one exception is `POST /v0/raw_events`, which runs on `events.formo.so` and authenticates with the project SDK write key instead.
**Response shape.** Successful responses return the resource directly (or `{ data: [...], total, page, size, has_more }` for paginated lists). HTTP status carries success/failure; there is no envelope wrapping success bodies.
**Errors.** Non-2xx responses from `api.formo.so` use the `Error` envelope, with two exceptions: some rate-limit rejections reply in plain text, and `POST /v0/raw_events` returns a plain `{ "error": "..." }` object. Treat the HTTP status as authoritative and parse defensively: `{ error: { code, message, doc_url, param?, details? } }`. Branch on the machine-readable `code` (see `ErrorCode` enum) and follow `doc_url` to the matching section of the errors reference.
**Idempotency.** Pass an `Idempotency-Key` header on write requests to alerts, boards, charts, contracts, segments, and import to make retries safe; the response is cached for 24 h and replayed on duplicate keys. Profile writes and `POST /v0/query` do not support it.'
version: 0.1.0
contact:
name: Formo
url: https://formo.so
servers:
- url: https://api.formo.so
description: API Server (boards, alerts, contracts, segments, profiles, query, import)
- url: https://events.formo.so
description: Events Server (event ingestion)
security:
- WorkspaceApiKey: []
tags:
- name: Events
description: Event ingestion API (events.formo.so)
paths:
/v0/raw_events:
post:
operationId: ingestEvents
summary: Ingest events
description: Send analytics events to Formo. This endpoint runs on events.formo.so (not api.formo.so). Authenticate with your project's SDK write key.
tags:
- Events
servers:
- url: https://events.formo.so
security:
- SdkWriteKey: []
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Event'
examples:
pageView:
summary: Track a page view
value:
- type: page
channel: web
version: '1'
anonymous_id: e397c4e7-5f0a-45d6-a06c-f34a809d8b82
user_id: ''
address: ''
event: ''
context:
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
locale: en-US
timezone: America/Los_Angeles
location: US
ref: ''
referrer: ''
utm_campaign: ''
utm_content: ''
utm_medium: ''
utm_source: ''
utm_term: ''
page_title: Dashboard | MyApp
page_url: https://myapp.com/swap/ethereum#/swap
page_path: /swap/ethereum
library_name: Formo Web SDK
library_version: 1.27.0
browser: chrome
device: desktop
os: Windows
screen_width: 1280
screen_height: 720
screen_density: 1.5
viewport_width: 1280
viewport_height: 604
properties:
url: https://myapp.com/swap/ethereum#/swap
path: /swap/ethereum
hash: '#/swap'
query: ''
original_timestamp: '2026-04-28T02:08:30.000Z'
sent_at: '2026-04-28T02:09:00.000Z'
message_id: 263434374239d12b797bf571c6045d6f9f9000a70f19f94d75ca485536606b27
walletConnect:
summary: Track a wallet connection
value:
- type: connect
channel: web
version: '1'
anonymous_id: 66b81795-cf59-43d1-80ab-ef48098b6e06
user_id: ''
address: '0xA39260F25D6ebBEAE4595977bDE410623A96E7Af'
event: ''
context:
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
locale: en-US
timezone: Europe/London
location: GB
page_title: MyApp - Swap & Bridge
page_url: https://myapp.com/earn/positions
library_name: Formo Web SDK
library_version: 1.27.0
browser: chrome
device: desktop
os: Windows
properties:
rdns: io.metamask
chain_id: 43114
provider_name: MetaMask
original_timestamp: '2026-04-27T20:04:54.000Z'
sent_at: '2026-04-27T20:05:00.000Z'
message_id: b0a1dc19c494df191e2cb0c56460f7472113e5858440b3d4f3798a070265f631
trackEvent:
summary: Track a custom event
value:
- type: track
channel: web
version: '1'
anonymous_id: 66b81795-cf59-43d1-80ab-ef48098b6e06
address: '0xA39260F25D6ebBEAE4595977bDE410623A96E7Af'
event: Chain Switched
context:
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
locale: en-US
timezone: Europe/London
location: GB
page_url: https://myapp.com/swap
library_name: Formo Web SDK
library_version: 1.27.0
browser: chrome
device: desktop
os: Windows
properties:
old_network: Arbitrum
new_network: BNB Chain
original_timestamp: '2026-04-27T23:05:38.000Z'
sent_at: '2026-04-27T23:05:42.000Z'
message_id: f4b2e8c1a59d3e7f6c8b9a02d5e4f1c3b8a7e6d5c4b3a291807e6d5c4b3a2918
identify:
summary: Identify a wallet
value:
- type: identify
channel: web
version: '1'
anonymous_id: 66b81795-cf59-43d1-80ab-ef48098b6e06
user_id: usr_42a91c2b
address: '0xA39260F25D6ebBEAE4595977bDE410623A96E7Af'
event: null
context:
library_name: Formo Web SDK
library_version: 1.27.0
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
locale: en-US
timezone: Europe/London
location: GB
page_url: https://myapp.com/dashboard
browser: chrome
device: desktop
os: Windows
properties:
rdns: io.metamask
provider_name: MetaMask
email: alice@example.com
display_name: alice.eth
original_timestamp: '2026-04-27T20:05:10.000Z'
sent_at: '2026-04-27T20:05:11.000Z'
message_id: 7e2a4b1c8d3f6e9a0b5c2d1e4f7a8b6c9d0e3f2a1b4c5d6e7f8a9b0c1d2e3f4a
transaction:
summary: Track an onchain transaction
value:
- type: transaction
channel: web
version: '1'
anonymous_id: 66b81795-cf59-43d1-80ab-ef48098b6e06
user_id: ''
address: '0xA39260F25D6ebBEAE4595977bDE410623A96E7Af'
event: ''
context:
library_name: Formo Web SDK
library_version: 1.27.0
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
locale: en-US
timezone: Europe/London
location: GB
page_url: https://myapp.com/swap
browser: chrome
device: desktop
os: Windows
properties:
status: confirmed
chain_id: 1
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
value: '0'
transaction_hash: '0x6f4c1f2c3a8b9e0d1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e'
function_name: transfer
function_args:
to: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
amount: '1000000000'
revenue: 250.5
currency: usd
original_timestamp: '2026-04-27T22:14:03.000Z'
sent_at: '2026-04-27T22:14:04.000Z'
message_id: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
responses:
'200':
description: Batch accepted. The body carries an ingestion summary when one is available, otherwise `{}`.
content:
application/json:
schema:
type: object
example: {}
'202':
description: 'Batch accepted for asynchronous processing. Returns `{ "queued": true }` when the batch was buffered for retry, an ingestion summary when one is available, otherwise `{}`.'
content:
application/json:
schema:
type: object
example:
queued: true
'400':
description: The request body is missing. A body that is present but not valid JSON returns 500 instead.
content:
application/json:
schema:
type: object
example:
error: Invalid request body
'401':
description: The request could not be authenticated.
content:
application/json:
schema:
type: object
example:
error: Unauthorized
'403':
description: Missing or invalid SDK write key. The body for this status is not the shape shown here.
content:
application/json:
schema:
type: object
example:
Message: User is not authorized to access this resource with an explicit deny
'500':
description: The batch could not be ingested, or the request body was not valid JSON.
content:
application/json:
schema:
type: object
example:
error: Internal Server Error
components:
schemas:
Event:
type: object
description: A single analytics event
required:
- type
- anonymous_id
- version
- channel
properties:
type:
type: string
enum:
- page
- connect
- disconnect
- chain
- signature
- transaction
- track
- detect
- identify
channel:
type: string
enum:
- web
- mobile
- server
- api
- import
description: Source of the event. The Formo Web SDK uses `web`; mobile SDK uses `mobile`; server SDK uses `server`. Use `api` for direct HTTP submissions and `import` for backfills.
version:
type: string
description: SDK schema version. Web SDK 1.x emits `1`; legacy clients emit `0`.
example: '1'
anonymous_id:
type: string
description: Anonymous visitor identifier
user_id:
type: string
nullable: true
description: Identified user ID
address:
type: string
nullable: true
description: Wallet address
event:
type: string
nullable: true
description: Event name (for track events)
context:
$ref: '#/components/schemas/EventContext'
properties:
$ref: '#/components/schemas/EventProperties'
original_timestamp:
type: string
format: date-time
sent_at:
type: string
format: date-time
message_id:
type: string
description: Unique ID for deduplication. Optional; a UUID is generated server-side when omitted.
EventProperties:
type: object
description: Event-specific properties. Can contain any key-value pairs relevant to the event.
additionalProperties: true
EventContext:
type: object
description: Contextual information about the event environment
properties:
user_agent:
type: string
locale:
type: string
description: e.g. en-US
timezone:
type: string
description: e.g. America/New_York
page_url:
type: string
page_path:
type: string
page_title:
type: string
page_query:
type: string
page_hash:
type: string
referrer_url:
type: string
referrer:
type: string
ref:
type: string
utm_source:
type: string
utm_medium:
type: string
utm_campaign:
type: string
utm_term:
type: string
utm_content:
type: string
browser:
type: string
device:
type: string
enum:
- desktop
- mobile
- tablet
os:
type: string
screen_width:
type: integer
screen_height:
type: integer
screen_density:
type: number
description: Pixel density of the device screen (devicePixelRatio)
viewport_width:
type: integer
description: Width of the browser viewport in pixels
viewport_height:
type: integer
description: Height of the browser viewport in pixels
location:
type: string
description: Geographic location country code (e.g., US, NG)
library_name:
type: string
library_version:
type: string
securitySchemes:
WorkspaceApiKey:
type: http
scheme: bearer
description: Workspace API key (e.g. `formo_xxx`). Create one in the Formo dashboard under Team Settings > API.
X402Payment:
type: apiKey
in: header
name: X-PAYMENT
description: x402 payment payload generated after the gateway returns a 402 challenge.
MPPPayment:
type: apiKey
in: header
name: Authorization
description: MPP payment authorization header, formatted as `Payment <payload>`, generated after the gateway returns a 402 challenge.
SdkWriteKey:
type: http
scheme: bearer
bearerFormat: JWT
description: 'Project SDK write key (a JWT), sent as `Authorization: Bearer <write key>`. This is NOT the `formo_...` workspace API key used on api.formo.so. Find it in the Formo dashboard under the project’s settings.'
x-api-scopes:
description: API key scopes control access to endpoints. Create keys with the required scopes in Team Settings > API.
scopes:
alerts:read: List and get alerts
alerts:write: Create, update, delete alerts (requires alerts:read)
boards:read: List and get boards and charts
boards:write: Create, update, delete boards and charts (requires boards:read)
contracts:read: List contracts
contracts:write: Create, update, delete contracts (requires contracts:read)
segments:read: List segments
segments:write: Create and delete segments (requires segments:read)
profiles:read: Search and get wallet profiles
profiles:write: Update wallet properties, manage labels, and import addresses (requires profiles:read)
query:read: Execute SQL analytics queries and read pre-built analytics endpoints (KPIs, top pages, lifecycle, retention, revenue, etc.)