Full API Specification
Complete Dunmore REST API specification. Give this page to an AI agent to get started.
Complete REST API specification for Dunmore. This single page contains everything an AI agent needs to create a project, register paid endpoints, configure integrations, and monitor revenue.
Base URL: https://api.dunmore.xyz
Authentication
All /api/* routes require an Authorization header.
Authorization: Bearer gf_live_...
Two auth methods are supported:
| Method | Token format | Used by | Scope |
|---|---|---|---|
| API Key | gf_live_... | Agents, SDK middleware | Project-scoped (/api/projects/:projectId/*) |
| Clerk JWT | eyJhbG... | Console UI, humans | User-scoped (/api/projects CRUD) |
Agents should use API keys. Create one in the console or via the API keys endpoint below.
Quick Start (5 API calls)
# 1. Create a project (requires Clerk JWT — do this in the console)
# Then use your gf_live_... API key for everything else:
# 2. Register a paid endpoint
curl -X POST https://api.dunmore.xyz/api/projects/proj_xxx/endpoints \
-H "Authorization: Bearer gf_live_..." \
-H "Content-Type: application/json" \
-d '{"path": "/analyze", "upstreamUrl": "https://my-agent.fly.dev/analyze", "priceUsd": "0.05"}'
# 3. Set up Slack notifications
curl -X POST https://api.dunmore.xyz/api/projects/proj_xxx/connectors \
-H "Authorization: Bearer gf_live_..." \
-H "Content-Type: application/json" \
-d '{"type": "slack", "config": {"webhookUrl": "https://hooks.slack.com/..."}, "eventTypes": ["payment.settled"]}'
# 4. Check revenue
curl https://api.dunmore.xyz/api/projects/proj_xxx/analytics/revenue \
-H "Authorization: Bearer gf_live_..."
# 5. List transactions
curl https://api.dunmore.xyz/api/projects/proj_xxx/transactions \
-H "Authorization: Bearer gf_live_..."
Response Format
All responses use this envelope:
// Success
{ "data": { ... } }
// Error
{ "error": { "code": "NOT_FOUND", "message": "Project not found", "status": 404 } }
ID Prefixes
| Prefix | Entity |
|---|---|
proj_ | Project |
ep_ | Endpoint |
pay_ | Payment |
key_ | API Key |
wh_ | Webhook |
whd_ | Webhook Delivery |
conn_ | Connector |
evt_ | Event |
gf_live_ | API Key secret |
whsec_ | Webhook signing secret |
Projects
Projects are the top-level container. All endpoints, keys, webhooks, and connectors belong to a project.
Create Project
POST /api/projects
Auth: Clerk JWT
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project display name |
slug | string | Yes | URL-safe identifier (lowercase, alphanumeric, hyphens) |
walletAddress | string | Yes | EVM address to receive USDC payments |
network | string | No | Chain ID (default: "eip155:8453" for Base mainnet) |
// Response 201
{
"data": {
"id": "proj_xxx",
"name": "My Agent",
"slug": "my-agent",
"ownerId": "user_xxx",
"walletAddress": "0x...",
"network": "eip155:8453",
"createdAt": "2025-02-22T12:00:00Z",
"updatedAt": "2025-02-22T12:00:00Z"
}
}
List Projects
GET /api/projects
Auth: Clerk JWT
Returns all projects owned by the authenticated user.
// Response 200
{ "data": [ { "id": "proj_xxx", "name": "...", ... } ] }
Get Project
GET /api/projects/:projectId
Auth: Clerk JWT
Update Project
PATCH /api/projects/:projectId
Auth: Clerk JWT
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New project name |
walletAddress | string | No | New wallet address |
network | string | No | New network |
Delete Project
DELETE /api/projects/:projectId
Auth: Clerk JWT
Deletes the project and all child records (endpoints, keys, webhooks, connectors, payments).
Endpoints
Endpoints represent individual paid API routes behind the Dunmore gateway.
Create Endpoint
POST /api/projects/:projectId/endpoints
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
path | string | Yes | URL path, must start with / (e.g., "/api/weather") |
upstreamUrl | string | Yes | Your API's public URL |
priceUsd | string | Yes | Price per request in USD (e.g., "0.001") |
// Response 201
{
"data": {
"id": "ep_xxx",
"projectId": "proj_xxx",
"path": "/api/weather",
"upstreamUrl": "https://my-agent.fly.dev/api/weather",
"priceUsd": "0.00100000",
"isActive": true,
"createdAt": "2025-02-22T12:00:00Z",
"updatedAt": "2025-02-22T12:00:00Z"
}
}
List Endpoints
GET /api/projects/:projectId/endpoints
Auth: API Key
Update Endpoint
PATCH /api/projects/:projectId/endpoints/:endpointId
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
priceUsd | string | No | New price (must be positive) |
upstreamUrl | string | No | New upstream URL |
isActive | boolean | No | Enable/disable |
Delete Endpoint
DELETE /api/projects/:projectId/endpoints/:endpointId
Auth: API Key
API Keys
API keys are scoped to a project and used for programmatic access. Secrets start with gf_live_.
Create API Key
POST /api/projects/:projectId/keys
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the key |
// Response 201
{
"data": {
"id": "key_xxx",
"name": "Agent Key",
"keyPrefix": "gf_live_xxxx",
"secret": "gf_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"createdAt": "2025-02-22T12:00:00Z"
}
}
The secret is only returned on creation. Store it securely.
List API Keys
GET /api/projects/:projectId/keys
Auth: API Key
Returns keys with prefixes only (no secrets). Only shows non-revoked keys.
Revoke API Key
DELETE /api/projects/:projectId/keys/:keyId
Auth: API Key
Webhooks
Webhooks deliver real-time event notifications to your URL via HTTP POST. Signed with HMAC-SHA256.
Create Webhook
POST /api/projects/:projectId/webhooks
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Public HTTPS endpoint |
eventTypes | string[] | Yes | Events to subscribe to (see Event Types) |
// Response 201
{
"data": {
"id": "wh_xxx",
"projectId": "proj_xxx",
"url": "https://my-agent.fly.dev/webhooks",
"secret": "whsec_xxx",
"eventTypes": ["payment.settled", "payment.failed"],
"isActive": true,
"createdAt": "2025-02-22T12:00:00Z"
}
}
The secret is only returned on creation. Use it to verify webhook signatures.
List Webhooks
GET /api/projects/:projectId/webhooks
Auth: API Key
Update Webhook
PATCH /api/projects/:projectId/webhooks/:webhookId
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
url | string | No | New webhook URL |
eventTypes | string[] | No | New event types |
isActive | boolean | No | Enable/disable |
Delete Webhook
DELETE /api/projects/:projectId/webhooks/:webhookId
Auth: API Key
Get Delivery Logs
GET /api/projects/:projectId/webhooks/:webhookId/deliveries
Auth: API Key
Returns the 50 most recent deliveries with status, HTTP response code, and timing.
Connectors
Connectors are pre-built integrations that subscribe to payment events. Each project can have one connector per type.
Supported Types
slack, discord, email, telegram, twilio, zapier, n8n, make, bigquery, supabase, google-sheets, dune, linear, segment, amplitude, posthog, pagerduty, datadog, opsgenie, teams
Create Connector
POST /api/projects/:projectId/connectors
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Connector type (see list above) |
config | object | Yes | Type-specific configuration |
eventTypes | string[] | Yes | Events to subscribe to |
Example — Slack:
curl -X POST https://api.dunmore.xyz/api/projects/proj_xxx/connectors \
-H "Authorization: Bearer gf_live_..." \
-H "Content-Type: application/json" \
-d '{
"type": "slack",
"config": { "webhookUrl": "https://hooks.slack.com/services/T.../B.../xxx" },
"eventTypes": ["payment.settled"]
}'
Example — Discord:
curl -X POST https://api.dunmore.xyz/api/projects/proj_xxx/connectors \
-H "Authorization: Bearer gf_live_..." \
-H "Content-Type: application/json" \
-d '{
"type": "discord",
"config": { "webhookUrl": "https://discord.com/api/webhooks/..." },
"eventTypes": ["payment.settled", "payment.failed"]
}'
Example — Email:
curl -X POST https://api.dunmore.xyz/api/projects/proj_xxx/connectors \
-H "Authorization: Bearer gf_live_..." \
-H "Content-Type: application/json" \
-d '{
"type": "email",
"config": { "to": "alerts@example.com" },
"eventTypes": ["payment.failed"]
}'
List Connectors
GET /api/projects/:projectId/connectors
Auth: API Key
Update Connector
PATCH /api/projects/:projectId/connectors/:connectorId
Auth: API Key
| Field | Type | Required | Description |
|---|---|---|---|
config | object | No | Updated configuration |
eventTypes | string[] | No | New event types |
isActive | boolean | No | Enable/disable |
Delete Connector
DELETE /api/projects/:projectId/connectors/:connectorId
Auth: API Key
Transactions
Payments processed through your endpoints.
List Transactions
GET /api/projects/:projectId/transactions
Auth: API Key
| Query param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
pageSize | number | 50 | Results per page (max 100) |
status | string | — | Filter: "verified", "settled", "failed" |
// Response 200
{
"data": [
{
"id": "pay_xxx",
"projectId": "proj_xxx",
"endpointId": "ep_xxx",
"payerWallet": "0x...",
"amountUsd": "0.00100000",
"status": "settled",
"txHash": "0x...",
"network": "eip155:8453",
"requestedAt": "2025-02-22T12:00:00Z",
"verifiedAt": "2025-02-22T12:00:01Z",
"settledAt": "2025-02-22T12:00:05Z",
"failedAt": null,
"errorMessage": null
}
],
"pagination": {
"total": 142,
"page": 1,
"pageSize": 50,
"hasMore": true
}
}
Get Transaction
GET /api/projects/:projectId/transactions/:paymentId
Auth: API Key
Analytics
Revenue Overview
GET /api/projects/:projectId/analytics/revenue
Auth: API Key
| Query param | Type | Default | Description |
|---|---|---|---|
period | string | "30d" | "today", "7d", "30d", or "all" |
// Response 200
{
"data": {
"overview": {
"totalRevenue": "14.25000000",
"transactionCount": 1420,
"settledCount": 1400,
"failedCount": 20,
"totalCount": 1420,
"uniquePayers": 38,
"period": "30d"
},
"series": [
{ "date": "2025-02-22", "revenue": "0.50000000", "transactionCount": 50 }
]
}
}
Conversion Funnel
GET /api/projects/:projectId/analytics/funnel
Auth: API Key
Returns verification-to-settlement conversion rates per endpoint.
Top Customers
GET /api/projects/:projectId/analytics/customers
Auth: API Key
| Query param | Type | Default | Description |
|---|---|---|---|
limit | number | 20 | Max results |
// Response 200
{
"data": [
{
"payerWallet": "0x...",
"totalSpend": "5.25000000",
"paymentCount": 525,
"avgPayment": "0.01000000",
"firstPaymentAt": "2025-02-01T12:00:00Z",
"lastPaymentAt": "2025-02-22T12:00:00Z"
}
]
}
Event Types
Events are emitted to the PostgreSQL outbox and dispatched to webhooks and connectors.
| Event | When |
|---|---|
payment.verified | Payment signature verified off-chain |
payment.settled | Payment confirmed on-chain |
payment.failed | Payment verification or settlement failed |
endpoint.created | New endpoint registered |
endpoint.pricing_changed | Endpoint price updated |
customer.first_payment | A wallet makes its first payment to your project |
customer.milestone | A wallet crosses a spending threshold ($10, $100, $1K, $10K) |
Event Payload Shape
{
"id": "evt_xxx",
"type": "payment.settled",
"timestamp": "2025-02-22T12:00:00Z",
"data": {
"payment_id": "pay_xxx",
"endpoint": "/api/weather",
"amount": "1000",
"currency": "USDC",
"network": "eip155:8453",
"payer_wallet": "0x...",
"seller_wallet": "0x...",
"tx_hash": "0x..."
},
"metadata": {
"project_id": "proj_xxx",
"environment": "production"
}
}
x402 Payment Flow
When a client hits a paid endpoint:
Client Gateway Facilitator
│ │ │
│── GET /api/weather ──▶│ │
│◀── 402 + accepts[] ──│ │
│ │ │
│ (sign EIP-3009) │ │
│ │ │
│── GET /api/weather ──▶│ │
│ Payment-Signature │── POST /verify ────────▶│
│ │◀── { valid: true } ─────│
│ │ │
│ │── Forward to upstream ──▶│
│◀── 200 + data ───────│ │
│ │ │
│ │── POST /settle (async) ─▶│
│ │ │── on-chain tx
402 Response Format (x402 v2)
{
"x402Version": 2,
"resource": { "url": "/api/weather" },
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "1000",
"payTo": "0x...",
"maxTimeoutSeconds": 30,
"extra": { "name": "USD Coin", "version": "2" }
}
]
}
Payment Header Format (x402 v2)
Base64-encoded JSON in the Payment-Signature header:
{
"x402Version": 2,
"accepted": {
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "1000",
"payTo": "0x...",
"maxTimeoutSeconds": 30,
"extra": { "name": "USD Coin", "version": "2" }
},
"payload": {
"signature": "0x...",
"authorization": {
"from": "0x...",
"to": "0x...",
"value": "1000",
"validAfter": "0",
"validBefore": "1740240000",
"nonce": "0x..."
}
},
"resource": { "url": "/api/weather" }
}
The accepted field must echo back one of the requirements from the accepts array in the 402 response.
Networks and Assets
| Network | Chain ID | USDC Address |
|---|---|---|
| Base Mainnet | eip155:8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Base Sepolia (testnet) | eip155:84532 | 0x036CbD53842c5426634e7929541eC2318f3dCF7e |
All amounts are in USDC atomic units (6 decimals). "1000" = $0.001 USDC.
SDK Middleware (Alternative to Gateway)
Instead of routing through the Dunmore gateway, you can embed payment verification directly in your server using SDK middleware.
Hono
npm install @dunmore/hono
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { dunmorePaywall } from "@dunmore/hono";
const app = new Hono();
app.get("/api/weather", dunmorePaywall({
apiUrl: "https://api.dunmore.xyz",
apiKey: "gf_live_...",
projectId: "proj_...",
priceUsd: "0.001",
payTo: "0x...",
network: "eip155:84532", // omit for mainnet
}), (c) => {
return c.json({ temperature: 72, unit: "F" });
});
serve({ fetch: app.fetch, port: 3000 });
Express
npm install @dunmore/express
import express from "express";
import { dunmorePaywall } from "@dunmore/express";
const app = express();
app.get("/api/weather", dunmorePaywall({
apiUrl: "https://api.dunmore.xyz",
apiKey: "gf_live_...",
projectId: "proj_...",
priceUsd: "0.001",
payTo: "0x...",
network: "eip155:84532", // omit for mainnet
}), (req, res) => {
res.json({ temperature: 72, unit: "F" });
});
app.listen(3000);
Route Summary
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /api/projects | Clerk JWT | Create project |
GET | /api/projects | Clerk JWT | List projects |
GET | /api/projects/:id | Clerk JWT | Get project |
PATCH | /api/projects/:id | Clerk JWT | Update project |
DELETE | /api/projects/:id | Clerk JWT | Delete project |
POST | /api/projects/:pid/endpoints | API Key | Create endpoint |
GET | /api/projects/:pid/endpoints | API Key | List endpoints |
PATCH | /api/projects/:pid/endpoints/:eid | API Key | Update endpoint |
DELETE | /api/projects/:pid/endpoints/:eid | API Key | Delete endpoint |
POST | /api/projects/:pid/keys | API Key | Create API key |
GET | /api/projects/:pid/keys | API Key | List API keys |
DELETE | /api/projects/:pid/keys/:kid | API Key | Revoke API key |
POST | /api/projects/:pid/webhooks | API Key | Create webhook |
GET | /api/projects/:pid/webhooks | API Key | List webhooks |
PATCH | /api/projects/:pid/webhooks/:wid | API Key | Update webhook |
DELETE | /api/projects/:pid/webhooks/:wid | API Key | Delete webhook |
GET | /api/projects/:pid/webhooks/:wid/deliveries | API Key | Delivery logs |
POST | /api/projects/:pid/connectors | API Key | Create connector |
GET | /api/projects/:pid/connectors | API Key | List connectors |
PATCH | /api/projects/:pid/connectors/:cid | API Key | Update connector |
DELETE | /api/projects/:pid/connectors/:cid | API Key | Delete connector |
GET | /api/projects/:pid/transactions | API Key | List transactions |
GET | /api/projects/:pid/transactions/:tid | API Key | Get transaction |
GET | /api/projects/:pid/analytics/revenue | API Key | Revenue data |
GET | /api/projects/:pid/analytics/funnel | API Key | Conversion funnel |
GET | /api/projects/:pid/analytics/customers | API Key | Top customers |
GET | /health | None | Health check |