Docs
Dashboard

Developer Portal

Programmatic access to the developer surfaces: OAuth applications, webhook subscriptions and their delivery log, developer usage metrics, the live status page, the changelog, and the community forum.

Authentication

The base URL for all requests is https://gullypay.xyz/api. Most endpoints require a valid JWT or API key sent as Authorization: Bearer <token>. Three read endpoints are public (no auth): the status page, the changelog, and listing community posts. Auth requirements are noted per endpoint below.

API keys live in the Auth API

API key creation, listing, and revocation are handled by the Auth module — see Getting Started for POST /auth/api-keys. This portal covers OAuth apps, webhooks, usage, status, changelog, and community.

Endpoints

OAuth Applications

POST/oauth/applicationsCreate an OAuth application (auth required)
GET/oauth/applicationsList your OAuth applications (auth required)

Webhooks

POST/merchants/:merchantId/webhooksCreate a webhook subscription (auth required)
GET/merchants/:merchantId/webhooksList webhook subscriptions (auth required)
GET/merchants/:merchantId/webhooks/deliveriesRecent deliveries + 24h stats (auth required)

Usage

GET/developer/usageDeveloper usage metrics for the authenticated user (auth required)

Status, Changelog & Community

GET/statusLive platform status page (public)
GET/changelogChangelog entries (public)
GET/community/postsList forum posts (public)
POST/community/postsCreate a forum post (auth required)
POST/community/posts/:postId/repliesReply to a forum post (auth required)

OAuth Applications

POST/oauth/applicationsCreate an OAuth application
Request Body
{
"name": "My Integration",
"redirectUris": ["https://app.example.com/oauth/callback"]
}
FieldTypeRequiredDescription
namestringYesDisplay name of the application
redirectUrisstring[]YesAllowed OAuth redirect URIs

The response includes the generated clientId and a one-time clientSecret. Only a hash of the secret is stored, so it is returned once at creation and cannot be retrieved again.

Response
{
"id": "app_abc123",
"developerId": "usr_abc123",
"name": "My Integration",
"clientId": "cli_9f8e7d6c5b4a...",
"redirectUris": ["https://app.example.com/oauth/callback"],
"clientSecret": "sec_a1b2c3d4...  (shown once)"
}
Store the client secret now

clientSecret is only returned in this response. If you lose it you must create a new application.

GET /oauth/applications lists the applications owned by the authenticated developer (without secrets).


Webhook Subscriptions

POST/merchants/:merchantId/webhooksCreate a webhook subscription
Request Body
{
"url": "https://app.example.com/webhooks/gullypay",
"events": ["payment_intent.succeeded", "order.created"]
}
FieldTypeRequiredDescription
urlstringYesHTTPS endpoint to receive events
eventsstring[]YesEvent types to subscribe to (use * for all)

The response includes a one-time signing secret. Deliveries are signed with HMAC-SHA256 and sent with an X-GullyPay-Signature header — see Webhooks for verification details.

Response
{
"id": "whs_abc123",
"merchantId": "merch_abc123",
"url": "https://app.example.com/webhooks/gullypay",
"events": ["payment_intent.succeeded", "order.created"],
"status": "active",
"secret": "3f9a...  (shown once)"
}

Delivery Log

GET/merchants/:merchantId/webhooks/deliveriesRecent deliveries + 24h stats

Returns the most recent delivery attempts plus 24-hour aggregates (total, success rate, average response time), all from the real webhook_deliveries table. Pass ?limit=<n> (default 50).

Response
{
"recent": [
  {
    "id": "whd_1",
    "eventType": "payment_intent.succeeded",
    "status": "success",
    "statusCode": 200,
    "durationMs": 142,
    "error": null,
    "createdAt": "2026-06-09T12:00:00Z"
  }
],
"stats": {
  "last24h": 87,
  "successRate": 98,
  "avgResponseMs": 156
}
}
QueryTypeRequiredDescription
limitnumberNoMax recent deliveries to return (default: 50)
Delivery retries are rolling out

Each event is currently delivered once. The exponential-backoff retry schedule and manual re-delivery documented in Webhooks are still being rolled out — reconcile against this delivery log until then.


Developer Usage

GET/developer/usageDeveloper usage metrics for the authenticated user

Returns real usage metrics for the authenticated developer over a rolling window. Pass ?days=<n> (1–365, default 30). Counts are computed from live tables: non-revoked API keys, x402 payments on the user's endpoints, active webhook subscriptions, recorded webhook deliveries, and logged API requests — plus a daily time series.

Response
{
"periodStart": "2026-05-10T12:00:00Z",
"periodEnd": "2026-06-09T12:00:00Z",
"activeKeys": 3,
"x402Transactions": 1240,
"webhookSubscriptions": 2,
"webhookDeliveries": 3110,
"apiCalls": 48200,
"timeseries": [
  { "date": "2026-06-08", "x402Transactions": 42, "apiCalls": 1610, "webhookDeliveries": 104 }
]
}
QueryTypeRequiredDescription
daysnumberNoRolling window in days, 1–365 (default: 30)

Status Page

GET/statusLive platform status page (public)

Public endpoint. Runs a live database probe and combines it with unresolved incidents to report per-service status. Overall status is one of operational, partial_outage, degraded, or major_outage.

Response
{
"status": "operational",
"services": {
  "api": "operational",
  "checkout": "operational",
  "x402": "operational",
  "webhooks": "operational",
  "mobile": "operational"
},
"incidents": [],
"checkedAt": "2026-06-09T12:00:00Z"
}

Changelog

GET/changelogChangelog entries (public)

Public endpoint. Returns the most recent changelog entries (up to 50).

Community Forum

GET/community/postsList forum posts (public)

Public. Returns forum posts; pass ?category=<slug> to filter by category.

POST/community/postsCreate a forum post
Request Body
{
"title": "How do I verify webhook signatures?",
"body": "I'm building a handler and want to validate the HMAC.",
"category": "webhooks"
}
FieldTypeRequiredDescription
titlestringYesPost title
bodystringYesPost body
categorystringNoCategory slug
POST/community/posts/:postId/repliesReply to a forum post
Request Body
{
"body": "Use HMAC-SHA256 with your subscription secret over the raw body."
}
FieldTypeRequiredDescription
bodystringYesReply body

Next Steps