Skip to Content
Endpoints

Endpoints

Every v1 endpoint needs an Authorization: Bearer pk_... header except where noted, and every list endpoint accepts the shared limit and cursor parameters described in the Overview.

Base URL: https://demo.stellarpassport.xyz

Organizations

List organizations

GET /api/v1/organizations

Returns only organizations that have a synced Luma calendar configured — not every organization on Passport. At the time of writing this returns 2, while at least 12 organizations own events in the catalogue.

total counts that filtered set, not all organizations. There is currently no endpoint that lists every organization.

This endpoint also ignores limit and cursor and reports a total rather than has_more / next_cursor.

{ "total": 2, "organizations": [ { "id": 7, "name": "Stellar Chile", "slug": "stellar-chile", "luma_url": "https://luma.com/telluscoop", "last_synced_at": null } ] }

Get an organization’s public page

GET /api/v1/organizations/[slug]/page

No API key required. This is the one public endpoint, intended for embedding an organization’s page.

Returns the organization’s profile plus an ordered list of content blocks. Each block has a type (link, text, and so on) and the fields that type needs.

{ "slug": "stellar-nigeria", "display_name": "Stellar Nigeria", "tagline": "Growing the Stellar Ecosystem in Nigeria", "cover_image_url": "https://...", "avatar_url": "https://...", "blocks": [ { "id": "8cf15f46-...", "type": "text", "body": "**Stellar Nigeria** is ..." }, { "id": "e61029f5-...", "type": "link", "label": "Register", "url": "https://...", "icon": "link", "style": "outline" } ], "updated_at": "2026-08-16T20:09:52.651Z" }

Events

These serve the Luma-synced calendar. For events people join inside Passport, see the internal surface below.

List events

GET /api/v1/events
ParameterDescription
statusupcoming, past, or all
org_idRestrict to one organization
{ "events": [ ... ], "has_more": false, "next_cursor": null }

Upcoming events

GET /api/v1/events/upcoming GET /api/v1/events/upcoming/[orgId]

A convenience shortcut for GET /api/v1/events?status=upcoming, optionally scoped to a single organization.


Hackathons

GET /api/v1/hackathons GET /api/v1/hackathons/[slug]

The list wraps results in hackathons; the detail endpoint returns the hackathon object directly, with additional fields such as team_min and team_max.

{ "hackathons": [ { "slug": "instawards-september", "name": "Instawards - September", "description": null, "image": null, "status": "registration_open", "format": "instawards", "hackathon_type": "chapter", "start_date": null, "end_date": null, "timezone": "UTC", "registration_opens_at": null, "submission_opens_at": null, "submission_deadline": null, "judging_deadline": null, "results_published_at": null, "prize_pool": null, "participant_count": 0 } ], "has_more": true, "next_cursor": "2026-08-20T16:11:49.159Z|68" }

Bounties

GET /api/v1/bounties GET /api/v1/bounties/[id]

Returns open, public bounties only. Bounties that are private, closed, or still in draft are never exposed here.

{ "bounties": [], "has_more": false, "next_cursor": null }

Profiles

GET /api/v1/profiles GET /api/v1/profiles/[username]

Profiles are the builder surface. Note the response key is builders, not profiles, and builders are addressed by their github_username.

{ "builders": [ { "github_username": "samjay8", "display_name": "Samuel Ojetunde", "avatar_url": "https://avatars.githubusercontent.com/u/197444055?s=200", "bio": null, "role_title": null, "location": null, "website_url": null, "twitter_handle": null, "telegram_handle": null, "discord_handle": null, "stellar_address": null, "is_featured": false, "created_at": "2026-08-28T18:17:20.235Z", "projects": [], "stats": { "totalCommits30d": 0, "activeDays30d": 0, "lastActiveDate": null } } ], "has_more": true, "next_cursor": "2026-08-28T22:25:17.184Z|4eff7598-..." }

The detail endpoint wraps its result in builder and adds fields the list omits, including github_id, discord_username, scf_tier, and a visibility object recording which fields the builder has chosen to make public.

{ "builder": { "github_username": "samjay8", "scf_tier": "verified", "visibility": { "bio": true, "wallet": true, "location": true, "projects": true } } }

Respect visibility: a field being present in the payload does not mean the builder wants it displayed.


Not available

These do not exist. If you have been given code that calls them, it is out of date:

PathUse instead
GET /api/v1/buildersGET /api/v1/profiles
GET /api/v1/events/:id/leaderboardNot yet available on v1

A public leaderboard endpoint is planned but not shipped.


Internal surface

Everything below is the unversioned /api/* surface. It powers Passport’s own front ends, including this website’s homepage. It is not versioned, has no stability guarantee, and can change without notice. It is documented here so that the homepage’s behaviour is explainable, not so that you build on it.

These events are a mix of Luma-synced records and events hosted on Passport. An event with a luma_url is synced and has no page on Passport — link it to its luma_url. An event without one is hosted on Passport and lives at /events/<slug>.

/events/<slug> responds 200 with an identical shell whether or not the event exists, resolving client-side, so you cannot probe validity by status code.

List events

GET /api/events
{ "events": [ { "id": 67, "name": "From Code to Mainnet: Shipping on Stellar", "slug": "from-code-to-mainnet-shipping-on-stellar", "description": "...", "start_date": "2026-09-05 12:00:00", "end_date": "2026-09-05 03:00:00", "branding": {}, "image": "https://images.lumacdn.com/...", "luma_url": "https://luma.com/5m7bx5wp", "featured_rank": null } ] }

featured_rank is null for ordinary events. A non-null integer marks the event as featured on the homepage, lower values first.

Get an event

GET /api/events/[slug]

By slug only — numeric ids return 404.

Leaderboard

GET /api/leaderboard
ParameterDescription
metricpoints (default)
windowall or month
limitRequested size. The endpoint returns at most 10 entries.
{ "metric": "points", "window": "month", "entries": [ { "position": 1, "value": 4050, "name": "Ada Example", "published": true, "profileUrl": "/builder/ada", "avatarUrl": "https://...", "rank": 3, "rankName": "Gold", "rankLabel": "Gold I", "rankInsignia": "/ranks/gold.svg?v=2" } ] }

Builders who have not opted into public display return published: false with a null name and a placeholder label such as "Builder #4". Their identity fields, including all rank fields, are null. They keep their position — drop them and the ranking develops gaps.

position uses standard competition ranking, so builders on equal points share a position and the next distinct score skips ahead.

rankInsignia is a path on the Passport host. Prefix it with the origin and keep the ?v= query, which is the artwork cache-buster.

Timestamps

start_date and end_date are formatted YYYY-MM-DD HH:mm:ss with no timezone offset, and the value is the event’s local wall-clock time. Do not treat it as UTC. Parse it consistently and avoid timezone-converting it for display until offsets are added.

Last updated on