API reference

REST API for Pro and Lifetime members — authentication, profiles, analytics, and rate limits.

ℹ️ The Belcard API requires a pro or Lifetime plan. All endpoints are at https://belcard.app/api/v1.

Authentication

Generate an API token from Dashboard → Settings → API tokens → New token. Pass the token as a Bearer header on every request:

Authorization: Bearer bc_live_xxxxxxxxxxxxxxxxxxxxxxxx

Token scopes

Choose which permissions to grant when creating a token. A token can have multiple scopes.

ScopeWhat it allows
profile:readRead your profile, links, and settings.
profile:writeUpdate display name, tagline, bio, links, and card theme.
analytics:readRead analytics events, summaries, and export data.

Tokens expire after 1 year by default. Set Never expires at creation time for persistent integrations. Revoke any token instantly from Dashboard → Settings → API tokens.

Profile endpoints

GET /api/v1/profile

Returns the authenticated user's profile. Requires profile:read.

curl https://belcard.app/api/v1/profile \
  -H "Authorization: Bearer bc_live_xxx"
{
  "id": "a1b2c3d4e5f6...",
  "username": "aayush",
  "displayName": "Aayush Sharma",
  "tagline": "Product Designer · Kathmandu",
  "bio": "Building things people use.",
  "cardTheme": "void",
  "isPublic": true,
  "links": [
    { "type": "linkedin", "label": "LinkedIn", "value": "https://linkedin.com/in/aayush" },
    { "type": "email",    "label": "Email",    "value": "aayush@example.com" },
    { "type": "phone",    "label": "Phone",    "value": "+977 9812345678" }
  ],
  "createdAt": 1714512000
}

PATCH /api/v1/profile

Update your profile. All fields optional — only send what you want to change. Requires profile:write.

curl -X PATCH https://belcard.app/api/v1/profile \
  -H "Authorization: Bearer bc_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tagline": "Senior Engineer · Leapfrog",
    "cardTheme": "aurora",
    "links": [
      { "type": "github", "label": "GitHub", "value": "https://github.com/aayush" },
      { "type": "url",    "label": "Portfolio", "value": "https://aayush.dev" }
    ]
  }'
// 200 OK
{ "ok": true }

Valid values for cardTheme: "void", "obsidian", "aurora", "solar".
Valid values for link type: "linkedin", "twitter", "github", "email", "phone", "url".
Sending links replaces your entire link list. Include all links you want to keep.

Analytics endpoints

GET /api/v1/analytics/summary

Aggregate event counts for a date range. Defaults to the last 30 days. Requires analytics:read.

curl "https://belcard.app/api/v1/analytics/summary?from=2025-01-01&to=2025-01-31" \
  -H "Authorization: Bearer bc_live_xxx"
{
  "from": "2025-01-01",
  "to": "2025-01-31",
  "totals": {
    "nfcTaps":      142,
    "profileViews": 318,
    "linkClicks":    87,
    "contactSaves":  24
  }
}

GET /api/v1/analytics/events

Paginated raw event list. Requires analytics:read.

Query paramTypeDefaultDescription
limitinteger50Results per page (max 200).
offsetinteger0Pagination offset.
typestringallFilter by event type (e.g. nfc_tap).
fromYYYY-MM-DD30 days agoStart date (inclusive).
toYYYY-MM-DDtodayEnd date (inclusive).
curl "https://belcard.app/api/v1/analytics/events?limit=20&type=nfc_tap" \
  -H "Authorization: Bearer bc_live_xxx"
{
  "events": [
    {
      "id": 1001,
      "eventType": "nfc_tap",
      "deviceType": "mobile",
      "countryCode": "NP",
      "city": "Kathmandu",
      "createdAt": 1714512000
    }
  ],
  "total": 142,
  "limit": 20,
  "offset": 0
}

Rate limiting

PlanRequests / minRequests / day
Pro6010,000
Lifetime12050,000

Rate limit state is returned in response headers on every request:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1714512060

When you exceed the limit, the API returns 429 Too Many Requests. Wait until X-RateLimit-Reset (a Unix timestamp) before retrying.

Error responses

All errors follow a consistent envelope:

{
  "error": "Unauthorized",
  "code": "AUTH_REQUIRED",
  "status": 401
}
HTTP statusCodeCause
400BAD_REQUESTMalformed body or missing required field.
401AUTH_REQUIREDMissing or invalid Bearer token.
403INSUFFICIENT_SCOPEToken lacks the required scope.
404NOT_FOUNDResource doesn't exist.
422VALIDATION_ERRORRequest body failed schema validation.
429RATE_LIMITEDToo many requests. Respect X-RateLimit-Reset.
500INTERNAL_ERRORServer error. Retry after a brief delay or contact support.

Webhooks Coming soon

Webhooks will POST signed payloads to your endpoint when events occur on your profile — such as an NFC tap, a contact save, or a link click. You'll be able to subscribe per event type. The payload will include a HMAC-SHA256 signature header for verification.

Planned for Q3 2025. Email us if webhooks are important to your use case — it helps us prioritise.