DC Member API — Developer Documentation v1.22.8

Programmatic access to your Dynamite Circle membership data — trips, events, profile, tickets, and more. For active DC members only. Designed for AI assistants, automation, and personal integrations.

For ALL active DC members. Every active DC member is eligible from day one — DC, DC BLACK, and trial accounts alike, no membership-age gating.

Open the user menu inside the DC member area and choose DC Member API Key to generate one.

Who can use this API?

The DC Member API is open to every active Dynamite Circle member — DC, DC BLACK, and trial accounts alike, with no membership-age requirement. It exposes the same data you can already see in the DC app — your trips, events, tickets, profile, inbox, and rooms — programmatically, so you can build personal automations or hand it to an AI assistant on your behalf.

If you're not a member yet, you can learn more about Dynamite Circle or apply to join. DC is a private community for established location-independent founders.

Authentication

All requests require an API key. Active members will see the DC Member API Key option in their profile dropdown on dc.dynamitecircle.com once eligible (currently rolling out to admins and testers first; broader access coming soon). Send the key as a Bearer token:

Authorization: Bearer dk_your_api_key

Base URL: https://api.dynamitecircle.com

Keys are issued to all active DC members (DC, DC BLACK, and trial accounts). Guests and inactive accounts return 403.

Official client — Agent Skill, CLI, Python library, MCP server

The fastest way to use the API — and to plug it into Claude Code, Codex CLI, Gemini CLI, Cursor, GitHub Copilot, or Claude Desktop — is the official DC client. Published on PyPI as dynamitecircle; source at github.com/dynamitecircle/dc. One self-contained Python file, stdlib only, that ships as four integrations from the same source: Agent Skill (auto-discovered via SKILL.md), CLI (dc …), Python library (from dc import DC), and MCP server (dc --mcp, optional mcp dep).

Install via PyPI (easiest)

pip install dynamitecircle
dc setup --api-key dk_your_api_key
dc self-test
dc profile

Same code as the repo, version-locked to the deployed API. View on PyPI →

Or clone the public repo

Useful if you want the MCP server config (.mcp.json at the repo root auto-registers every endpoint as an mcp__dc__* tool when you open the dir in Claude Code), or want to vendor the file via git submodule / subtree:

git clone https://github.com/dynamitecircle/dc.git
cd dc
python3 py/dc.py setup --api-key dk_your_api_key
python3 py/dc.py profile

Python library

from dc import DC

dc = DC()
dc.profile()
dc.trips(past=True, limit=10)
dc.event_rsvp("<eventID>", "yes")
dc.locator(sections="homeCity,favoriteCities")

MCP server (Claude Desktop, Cursor, Codex MCP, Cline, etc.)

The same file runs as an MCP server so MCP-compatible clients call every endpoint as a tool:

pip install dynamitecircle[mcp]
dc --mcp

Codex CLI and Gemini CLI auto-discover the skill via AGENTS.md / GEMINI.md (both symlinked to CLAUDE.md in the repo). See the repo README for per-tool setup (Claude Desktop, Codex CLI, Gemini CLI, Cursor) and update strategies (pip install --upgrade, git clone, submodule, subtree, symlink).

Rate limits

TierPer minutePer day
DC member10300
DC BLACK member603,000

Rate limit headers on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-RateLimit-Daily-Remaining.

Response format

// Success
{ "ok": true, "data": { ... } }

// Error
{ "ok": false, "error": "error_code", "message": "Human-readable message" }

Endpoints

Announcements

GET /announcements — List recent announcements

Returns the most recent announcements from DC's broadcast channels — official updates from the DC team and chapter staff (DC, DCBKK, DCMEX, DC BLACK, etc.). Same content you see in the app's announcements channels, in a flat newest-first feed. Visibility mirrors the app: DC members see DC-scope announcements; DC BLACK members and staff additionally see DC BLACK announcements. There is no posting, replying, or per-channel filtering — announcements are intentionally one-way and minimal.

Query parameters

  • limit number default: 10

    Max announcements to return (1-50)

  • cursor string

    Opaque cursor from a previous response's `nextCursor`

Response

  • announcements object[]

    Newest-first list of announcements visible to the caller

    • createdAt string

      When the announcement was posted (ISO 8601)

    • content string

      Markdown content of the announcement

    • announcementURL string

      Deep-link back to the announcement in the DC app (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same announcement.

    • author object

      Author of the announcement (DC team member or chapter lead)

      • userID string

        Author user ID

      • userName string

        Username (used in profile URL)

      • displayName string

        Display name

      • photo string

        Profile photo URL

      • profileURL string

        Link to the author's profile on DC

  • nextCursor string

    Cursor for the next (older) page, or null when there are no more

Example: Latest announcements (default 10)

{
  "data": {
    "announcements": [
      {
        "announcementURL": "https://dc.dynamitecircle.com/room/abc/channel?m=xyz",
        "author": {
          "displayName": "Dan Andrews",
          "photo": "https://...",
          "profileURL": "https://dc.dynamitecircle.com/profile/DanAndrews",
          "userID": "1",
          "userName": "DanAndrews"
        },
        "content": "DCBKK 2026 early-bird tickets are live until Friday — see you in Bangkok!",
        "createdAt": "2026-04-30T10:00:00.000Z"
      }
    ],
    "nextCursor": "MTcxNzIwMDAwMDAwMA"
  },
  "ok": true
}

GET /announcements/latest — Latest announcement per channel (quick overview)

Returns the **single most recent announcement from each visible channel** — a one-shot overview rather than a paged feed. Useful as a "what's new across DC?" quick check before drilling into the full feed via `GET /announcements`. Visibility rules are identical to `/announcements`: DC members see DC-scope channels; DC BLACK members and staff additionally see DC BLACK channels. No pagination — the result size equals the number of dispatch channels you can see (currently ~4).

Response

  • announcements object[]

    One most-recent announcement from each visible dispatch channel. Same per-item shape as `GET /announcements`.

Example: Latest announcement per channel

{
  "data": {
    "announcements": [
      {
        "announcementURL": "https://dc.dynamitecircle.com/room/abc/channel?m=xyz",
        "author": {
          "displayName": "Dan Andrews",
          "photo": "https://...",
          "profileURL": "https://dc.dynamitecircle.com/profile/DanAndrews",
          "userID": "1",
          "userName": "DanAndrews"
        },
        "content": "DCBKK 2026 early-bird tickets are live until Friday — see you in Bangkok!",
        "createdAt": "2026-04-30T10:00:00.000Z"
      }
    ]
  },
  "ok": true
}

Profile

GET /profile — Get your own profile

Returns your own full profile — every field the in-app profile editor surfaces to you, plus tier-derived state. Same shape regardless of tier (DC and DC BLACK members get identical own-profile payloads). Use `PATCH /profile` to update editable fields.

Response

  • userID string

    Your unique member ID.

  • userName string

    Your DC username — appears in your profile URL.

  • displayName string

    Your display name shown across the DC app.

  • photo string

    Profile photo URL.

  • profileURL string

    Link to your public profile on DC (canonical host).

  • shortURL string

    Branded short link (dc.mba) to your public profile.

  • headline string

    One-sentence elevator pitch shown at the top of your profile.

  • industry string

    Primary business industry (predefined bracket).

    Values: SaaS & Tech, Marketing Agency, Productized Services, Ecommerce & Amazon, Courses and Info Products, Affiliate, Content Creation, or Ad Revenue, Professional Services & Industry Specific Consulting, Real Estate and Investing, Coaching, Other

  • joinedDate string

    Date you joined DC (YYYY-MM-DD).

  • tier string

    Your membership tier.

    Values: dcc, dcb

  • bizName string

    Name of your primary business.

  • bizDesc string

    Description of your primary business (plain text or HTML).

  • bizRevenue string

    Annual revenue bracket of your primary business.

    Values: No real income yet, it's still getting off the ground., I recently exited a business., $10K+, $50K+, $100K+, $250K+, $300K+, $600K+, $1M+, $2M+, $3M+, $4M+, $7M+, $10M+, $20M+, $35M+, $60M+, $100M+, Prefer not to say

  • bizRevenueIsPrivate boolean

    Visibility of your revenue. `true` = hidden from other DCers (only DC staff can see it); `false` = visible to all DCers.

  • bizTeam string

    Team size bracket of your primary business.

    Values: None, 1-2, 3-5, 6-9, 10-14, 15-19, 20-34, 35-49, 50-74, 75-99, 100+, Prefer not to say

  • bizTeamIsPrivate boolean

    Visibility of your team size. `true` = hidden from other DCers (only DC staff can see it); `false` = visible to all DCers.

  • bizWeb string

    Public website for your primary business.

  • yearsInBiz string

    How long you have been on the entrepreneurial path.

    Values: Less than one year, 1-2 years, 3-6 years, 7-9 years, 10-15 years, 15-20 years, More than 20 years

  • connectIsPrivate boolean

    Visibility of your "who I want to meet" answer. `true` = hidden from other DCers (only DC staff can see it); `false` = visible to all DCers.

  • linkedin string

    LinkedIn handle.

  • twitter string

    Twitter/X handle.

  • github string

    GitHub handle. Required for access to the public DC client repo.

Example: Get your profile

{
  "data": {
    "bizName": "Acme Inc",
    "bizWeb": "https://example.com",
    "displayName": "Jane Doe",
    "headline": "Founder at Acme Inc",
    "industry": "SaaS & Tech",
    "joinedDate": "2020-01-15",
    "photo": "https://storage.googleapis.com/dc-nav.appspot.com/...",
    "profileURL": "https://dc.dynamitecircle.com/profile/JaneDoe",
    "tier": "dcb",
    "userID": "1234",
    "userName": "JaneDoe"
  },
  "ok": true
}

PATCH /profile — Update profile fields

Update allowed profile fields. Only the fields you include will be changed. Location, photo, and gender cannot be updated via API.

Request body

  • headline string

    One-sentence elevator pitch shown at the top of your DC profile (max 64 chars).

  • bizName string

    Name of the main business you run or are primarily focused on right now (max 256 chars). You can list other businesses in `bizOther`.

  • bizDesc string

    Description of your primary business. Plain text or HTML, up to 1600 chars.

  • bizWeb string

    Public website for your primary business — single URL only (max 256 chars).

  • bizIndustry string

    Category your primary business fits into. Must be one of the predefined industries.

    Values: SaaS & Tech, Marketing Agency, Productized Services, Ecommerce & Amazon, Courses and Info Products, Affiliate, Content Creation, or Ad Revenue, Professional Services & Industry Specific Consulting, Real Estate and Investing, Coaching, Other

  • bizRevenue string

    Approximate annual revenue (in U.S. dollars) of your primary business over the last 12 months. Predefined bracket.

    Values: No real income yet, it's still getting off the ground., I recently exited a business., $10K+, $50K+, $100K+, $250K+, $300K+, $600K+, $1M+, $2M+, $3M+, $4M+, $7M+, $10M+, $20M+, $35M+, $60M+, $100M+, Prefer not to say

  • bizRevenueIsPrivate boolean

    Visibility of your revenue. `true` = hidden from other DCers (only DC staff can see it); `false` = visible to all DCers.

  • bizTeam string

    Number of full-time and part-time team members in your primary business. Predefined bracket.

    Values: None, 1-2, 3-5, 6-9, 10-14, 15-19, 20-34, 35-49, 50-74, 75-99, 100+, Prefer not to say

  • bizTeamIsPrivate boolean

    Visibility of your team size. `true` = hidden from other DCers (only DC staff can see it); `false` = visible to all DCers.

  • yearsInBiz string

    How long you have been on the entrepreneurial path. Used for matching with other members. Predefined bracket.

    Values: Less than one year, 1-2 years, 3-6 years, 7-9 years, 10-15 years, 15-20 years, More than 20 years

  • bizOther string

    Other businesses you currently operate. Feel free to share URL, short description, and year started for each (up to 1600 chars).

  • bizPast string

    Previous business exits and entrepreneurial experience worth listing (up to 1600 chars).

  • linkedin string

    LinkedIn username only (no URL prefix). 1-50 chars: letters, digits, `.`, `_`, `-`.

  • twitter string

    Twitter/X username only (no URL prefix). 1-15 chars: letters, digits, `_`.

  • instagram string

    Instagram username only (no URL prefix). 1-30 chars: letters, digits, `.`, `_`.

  • facebook string

    Facebook username only (no URL prefix). 5-50 chars: letters, digits, `.`.

  • focusmate string

    Focusmate username only (no URL prefix). 3-50 chars: letters, digits, `_`, `-`.

  • github string

    GitHub username only (no URL prefix). 1-39 chars per GitHub's rules: letters, digits, `-`. Required to be granted access to the public DC client repo — set this to opt in.

  • whatsapp string

    WhatsApp phone number in international format — `+` followed by 5-16 digits, no dashes or spaces. Required if you want to be added to the DC WhatsApp community. Always private — only visible to DC staff.

  • expertise string

    Areas you might consider yourself an expert in — skills you can use to help other members (up to 1600 chars).

  • ama string

    Topics other members can ask you about, in your field of expertise (up to 1600 chars).

  • hobbies string

    Your non-business hobbies — games, camping, art, sports, anything (up to 1600 chars).

  • goal string

    Your current business challenge or goal. Used internally to match you with other members who can help (up to 1600 chars).

  • connect string

    What kinds of community members you would like to connect with. Used to send recommendations of relevant DCers (up to 1600 chars). Set `connectIsPrivate: true` to keep this visible only to DC staff.

  • connectIsPrivate boolean

    Visibility of your "who I want to meet" answer. `true` = hidden from other DCers (only DC staff can see it); `false` = visible to all DCers.

  • locs string

    Cities or regions you frequently visit. Helps surface trip overlaps with other members (up to 1600 chars).

  • nickname string

    Display name override — what other DCers see in addition to your real name (max 256 chars).

  • spouseName string

    Name of your spouse or partner — used only for the DCBKK partner pass. Always private (DC staff only).

  • shirtSize string

    T-shirt size — used when DC sends event swag.

    Values: XS, S, M, L, XL, XXL, XXXL

  • diet string

    Dietary restrictions — used when DC plans event meals.

    Values: No Restrictions, Vegan, Vegetarian, Gluten-Free, Dairy/Lactose-Free

Response

  • updated string[]

    List of field names that were updated

Example: Update headline and LinkedIn

{
  "headline": "Building SaaS for nomads",
  "linkedin": "janedoe"
}
{
  "data": {
    "updated": [
      "headline",
      "linkedin"
    ]
  },
  "ok": true
}

Trips

GET /trips — List your trips

Returns your upcoming trips by default. Add `?past=true` to include past trips. **For "who should I meet on this trip?"** fetch `GET /trips/:tripID` (or the discovery-only `GET /trips/:tripID/discovery`) — both return the ranked top-10 DCers + AI-written summaries + the full pool of locals and visitors in town during the trip window. The list response below does NOT include the discovery block (lazy by design — discovery is a much heavier payload).

Query parameters

  • past boolean default: false

    Include past trips.

  • limit number default: 50

    Max results (1-100).

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • trips object[]

    Array of your trips. List responses ship a lean trip shape — `discovery` is always `null` on list reads to keep payloads small; fetch `GET /trips/:tripID` to get the enriched discovery block.

    • tripID string

      Trip ID

    • note string

      Trip note/description

    • location object

      Trip destination (city-level)

      • placeID string

        Google Place ID

      • name string

        Place name

      • city string

        City

      • country string

        Country

      • countryCode string

        ISO country code

      • region string

        Region / state / prefecture

      • regionCode string

        Region short code

      • description string

        Friendly display string

      • lat number

        Latitude

      • lon number

        Longitude

      • latLon string

        "lat,lon" string

      • locHash string

        Geohash for the location

      • utcOffsetMins number

        UTC offset in minutes

    • startDate string

      Start date (ISO 8601)

    • endDate string

      End date (ISO 8601)

    • eventID string

      DC event ID if this trip was created from an event, otherwise `null`.

    • createdAt string

      Trip created-at (ISO 8601).

    • updatedAt string

      Trip updated-at (ISO 8601).

    • points object[]

      Embedded venue/idea notes (up to 20 per trip). Each `{ note, place }` where `place` is the full resolved Google Place object or `null` for note-only items.

    • roomID string

      Linked auto-created chat room for this trip, or `null` if no room was provisioned.

    • discovery object

      Always `null` on list reads. Fetch `GET /trips/:tripID` for the enriched discovery block.

  • nextCursor string

    Cursor for the next page, or `null` if no more trips.

Example: List upcoming trips

{
  "data": {
    "trips": [
      {
        "endDate": "2026-04-17T00:00:00.000Z",
        "location": {
          "city": "Bangkok",
          "country": "Thailand",
          "countryCode": "TH",
          "description": "Bangkok, Thailand",
          "lat": 13.7563309,
          "latLon": "13.7563309,100.5017651",
          "lon": 100.5017651,
          "name": "Bangkok",
          "placeID": "ChIJ82ENKDJgHTERIEjiXbIAAQE",
          "region": "Bangkok",
          "regionCode": "10",
          "utcOffsetMins": 420
        },
        "note": "DCBKK week",
        "startDate": "2026-04-10T00:00:00.000Z",
        "tripID": "abc123"
      }
    ]
  },
  "ok": true
}

POST /trips — Create a trip

Create a new trip. Provide exactly one of `placeID` or `eventID` — the server resolves the location (city, country, country code) automatically. Use `GET /places/search` to find a placeID by city/country name first, or pass an `eventID` from `/events` to create a trip to that event's city. **Trip points** (optional `points` array, up to 20 per trip): each item is `{ note: string (max 280 chars), noteHTML?: string, placeID?: string }`. The optional `placeID` is resolved against Google Places at write time and the full Place object (city, country, lat/lon, name, etc.) is stored on the trip — so reads don't do any lookups. `noteHTML` preserves the same rich text field the web trip editor stores for formatted notes, links, and mentions; `note` remains the required plain-text fallback. Notes without a placeID are valid ("remember to book a coworking space"). Pass an unknown / expired Google placeID → 400 with a clear error.

Request body

  • startDate string required

    Start date (ISO 8601)

  • endDate string required

    End date (ISO 8601)

  • placeID string

    Google Place ID for the destination. Look one up via `GET /places/search`. **Pass exactly one of `placeID` or `eventID`** — sending both rejects with 400.

  • eventID string

    DC event ID. Server uses the event's city placeID. **Pass exactly one of `placeID` or `eventID`** — sending both rejects with 400.

  • note string

    Trip note

  • points object[]

    Optional. Up to 20 trip points (venues / ideas / notes). Each item: `{ note: string (max 280 chars), noteHTML?: string, placeID?: string }`. The optional `placeID` is resolved against Google Places at write time. Notes without a place are valid.

Response

  • trip ApiTrip

    The created trip

Example: Create a trip to Lisbon by placeID

{
  "endDate": "2026-05-10",
  "note": "Co-working week",
  "placeID": "ChIJ-ZRLfIQzMBQR2bAQQ8sZh90",
  "startDate": "2026-05-01"
}
{
  "data": {
    "trip": {
      "endDate": "2026-05-10T00:00:00.000Z",
      "eventID": null,
      "location": {
        "city": "Lisbon",
        "country": "Portugal",
        "countryCode": "PT",
        "description": "Lisbon, Portugal",
        "lat": 38.7222524,
        "latLon": "38.7222524,-9.1393366",
        "lon": -9.1393366,
        "name": "Lisbon",
        "placeID": "ChIJ-ZRLfIQzMBQR2bAQQ8sZh90",
        "region": "Lisbon",
        "regionCode": "11",
        "utcOffsetMins": 60
      },
      "note": "Co-working week",
      "startDate": "2026-05-01T00:00:00.000Z",
      "tripID": "new123"
    }
  },
  "ok": true
}

Example: Create a trip linked to an event

{
  "endDate": "2026-05-22",
  "eventID": "sWnllj1DW2jLMZ1n2KWB",
  "note": "Attending DCBKK",
  "startDate": "2026-05-18"
}
{
  "data": {
    "trip": {
      "endDate": "2026-05-22T00:00:00.000Z",
      "eventID": "sWnllj1DW2jLMZ1n2KWB",
      "location": {
        "city": "Bangkok",
        "country": "Thailand",
        "countryCode": "TH",
        "description": "Bangkok, Thailand",
        "lat": 13.7563309,
        "latLon": "13.7563309,100.5017651",
        "lon": 100.5017651,
        "name": "Bangkok",
        "placeID": "ChIJ82ENKDJgHTERIEjiXbIAAQE",
        "region": "Bangkok",
        "regionCode": "10",
        "utcOffsetMins": 420
      },
      "note": "Attending DCBKK",
      "startDate": "2026-05-18T00:00:00.000Z",
      "tripID": "new456"
    }
  },
  "ok": true
}

PATCH /trips/:tripID — Update a trip

Update one or more fields on an existing trip. Only include the fields you want to change. To change destination, provide either `placeID` or `eventID` and the full location will be re-resolved. **Trip points**: passing `points` replaces the entire array (it's not a patch within the array). Up to 20 items, same shape as `POST /trips`: `{ note: string (max 280 chars), noteHTML?: string, placeID?: string }`. To clear all points, pass `points: []`.

Path parameters

  • tripID e.g. abc123

    The trip ID to update

Request body

  • startDate string

    New start date (ISO 8601)

  • endDate string

    New end date (ISO 8601)

  • placeID string

    New destination — Google Place ID

  • eventID string

    New destination — DC event ID (uses event's city). Pass `null` to unlink without changing the location.

  • note string

    Updated note

  • points object[]

    Optional. Replace the entire `points` array (not a patch within). Up to 20 items, same shape as `POST /trips`. Pass `[]` to clear all points.

Response

  • trip ApiTrip

    The updated trip

DELETE /trips/:tripID — Delete a trip

Permanently delete one of your trips. Removes the trip doc and its linked chat room (`trip.roomID`). The destination chapter's upcoming-trip count is recomputed in the background. **Owner-only** — you can only delete trips you created. The action is irreversible; deleted trips don't go to a trash collection.

Path parameters

  • tripID e.g. abc123

    The trip ID to delete

Response

  • deleted boolean

    Always `true` on success. The endpoint returns 404 if the trip never existed or 403 if you don't own it.

GET /trips/overlaps — Find overlapping trips

Find other members whose trips overlap with yours by city + date range. **This is a narrow date-window match, NOT the AI-ranked discovery pool.** For the full set of DCers you could meet on a trip — including locals in town and AI-written "why you should meet them" summaries — fetch `GET /trips/:tripID/discovery` (or `GET /trips/:tripID`, which embeds the same `discovery` block). The discovery pool is typically 5–10× larger than `/trips/overlaps` because it includes locals and event attendees in addition to date-overlap visitors, and it carries ranked top-10 picks with AI summaries that this endpoint does not. Use `/trips/overlaps` for the simple "who is travelling here at the same time as me" question. Use `/trips/:tripID/discovery` for "who should I meet on this trip?".

Query parameters

  • limit number default: 10

    Max trips to check (1-20)

Response

  • overlaps object[]

    One entry per upcoming trip of yours that has overlapping trips from other DCers

    • trip object

      Your trip

      • tripID string

        Trip ID

      • eventID string

        Linked event ID (null if not linked)

      • note string

        Trip note

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Trip destination

        • placeID string

          Google Place ID

        • name string

          Display name

        • city string

          City

        • country string

          Country

        • countryCode string

          ISO country code

    • matches object[]

      Other members whose trips overlap with yours in this destination

      • member object

        The other member's profile (same shape as `/profile` for other DCers)

        • userID string

          Member ID

        • userName string

          Username (handle)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Profile URL on DC

        • headline string

          Profile headline

        • industry string

          Business industry

        • joinedDate string

          Join date (YYYY-MM-DD)

      • trip object

        Their overlapping trip

        • tripID string

          Their trip ID

        • note string

          Their trip note (if shared)

        • startDate string

          Their start date (ISO 8601)

        • endDate string

          Their end date (ISO 8601)

      • overlapDays number

        Number of overlapping days between your trip and theirs

Example: Find who else is in Bangkok during your trip

{
  "data": {
    "overlaps": [
      {
        "matches": [
          {
            "member": {
              "displayName": "Jane Doe",
              "profileURL": "https://dc.dynamitecircle.com/profile/JaneDoe",
              "userID": "123"
            },
            "overlapDays": 5,
            "trip": {
              "endDate": "2026-04-20T00:00:00.000Z",
              "startDate": "2026-04-12T00:00:00.000Z",
              "tripID": "theirtrip1"
            }
          }
        ],
        "trip": {
          "endDate": "2026-04-17T00:00:00.000Z",
          "location": {
            "city": "Bangkok"
          },
          "startDate": "2026-04-10T00:00:00.000Z",
          "tripID": "mytrip1"
        }
      }
    ]
  },
  "ok": true
}

GET /trips/:tripID — Get a single trip

Single-trip read with the full payload. **This is the canonical endpoint for "who should I meet on this trip?"** — the response embeds a complete `discovery` block (ranked top-10 picks with AI summaries, the full pool of locals + visitors, events in town, and date-overlapping trips). If you only want the discovery block without the trip body, use `GET /trips/:tripID/discovery`. **Key discovery fields agents almost always want:** - `discovery.people` — **ranked top-10 DCers to meet** on this trip, each carrying `score` (higher = better match), mini `profile` (userID, userName, displayName, photo, headline), `reason` (`local` / `visiting` / `event-attendee`), `overlapDays`, `detail`. Sourced from a vector-search + business-context ranking, not just date overlap. - `discovery.whyToMeet` — **AI-written "why you should meet them" paragraph** for each of the top-10, keyed by userID, each `{ text, generatedAt }`. The most useful AI signal in the whole trip product — agents should surface this verbatim when introducing a match. - `discovery.fullPool` — every visible DCer travelling or local during the trip window (typically 5–10× larger than `/trips/overlaps`, which only returns date-window matches). Same row shape as `people` but no `score`. - `discovery.overlappingTrips` — other DCers travelling at the same time/place, each with mini profile attached so no second fetch is needed. This is the same data that `/trips/overlaps` returns, embedded here for convenience. - `discovery.events` — events in the destination city during the trip window. - `discovery.generatedAt` — when the discovery cache was last refreshed. **Also included:** `points` — up to 20 venue/idea notes with optional Google Place data, plus a linked `roomID` for the auto-created trip coordination room. Hidden + guest profiles are filtered out from all discovery lists. The `discovery` block is `null` for newly-created trips until the background sync task runs (~seconds — call `POST /trips/:tripID/refresh` to force-recompute). Open to any authenticated DCer (you can read other DCers' trips too).

Path parameters

  • tripID e.g. abc123

    The trip ID

Response

  • trip ApiTrip

    The full trip including points and the enriched discovery block

POST /trips/:tripID/refresh — Trigger a trip refresh

Owner-only sync trigger. Enqueues a deduped background job that recomputes the trip's discovery (overlapping people, events, AI blurbs). Spammy reloads coalesce. Returns 202 Accepted immediately; the cached `discovery` block on the trip doc updates when the job completes.

Path parameters

  • tripID e.g. abc123

    The trip ID to refresh

Response

  • accepted boolean

    Whether the refresh was accepted

GET /trips/:tripID/discovery — Get the discovery block for a trip

Discovery-only read for a trip. Returns the same `discovery` block as `GET /trips/:tripID` (people, fullPool, whyToMeet, events, overlappingTrips) without the trip body. Useful for callers that just want "who should I meet on this trip?" — the AI agent gets the ranked top-10 + their `whyToMeet` paragraphs in a single request. Use `?include=` to subset the response — comma-separated from `people,fullPool,whyToMeet,events,overlappingTrips`. Default is all. Common patterns: - `?include=people,whyToMeet` — top-10 picks + their AI-written "why you should meet them" paragraphs (keyed by userID, each carrying `{ text, generatedAt }`) - `?include=fullPool` — every visible DCer travelling/local during the trip window - `?include=events` — just events in the destination city during the trip window Open to any authenticated DCer; hidden + guest profiles are filtered out.

Path parameters

  • tripID e.g. abc123

    The trip ID

Query parameters

  • include string

    Optional. Comma-separated subset of `people,fullPool,whyToMeet,events,overlappingTrips`. Default = all five.

Response

  • discovery object

    The trip's cached discovery block. `null` if the trip has no discovery yet (newly created, sync hasn't run). Filtered to the keys requested in `?include=`.

Events

GET /events — List upcoming events

Returns upcoming DC events, sorted by date. Add `?past=true` to include past events. **See also:** For events by name or topic (`q='productivity'`, `q='DCBKK 2026'`), `POST /search/events` searches title + description directly — faster than paginating this date-sorted list. Combine with `?cityID`, `?country`, `?since`, `?until` filters for narrower scopes.

Query parameters

  • past boolean default: false

    Include past events.

  • limit number default: 20

    Max results (1-50).

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • events object[]

    Array of events

    • eventID string

      Event ID

    • name string

      Event name

    • slug string

      URL slug

    • eventURL string

      Link to event on DC (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same event — equivalent destination, shorter for display / sharing.

    • description string

      Full description (markdown)

    • descriptionShort string

      Short description (markdown)

    • eventType string

      Event type (dcbkk, junto, meet-up, etc.)

    • headerImage string

      Header image URL

    • city object

      Event city

      • name string

        City name

      • country string

        Country

      • countryCode string

        ISO country code

      • placeID string

        Google Place ID for the city — pass to POST /trips to create a trip to this event

    • venue object

      Event venue (the specific building/place inside the event city). `null` until a venue is announced (TBA events).

      • name string

        Venue name (e.g. "Hilton Mexico City Reforma")

      • placeID string

        Google Place ID for the venue — pass to Google Maps for directions, or to `GET /places/:placeID` for full details

      • city string

        City the venue is in (usually matches `event.city.name`, but may differ for satellite venues)

      • country string

        Country

      • countryCode string

        ISO country code

      • region string

        State / region / administrative area

      • lat number

        Latitude (decimal degrees)

      • lon number

        Longitude (decimal degrees)

    • venueInfo string

      Free-text note about the venue (e.g. "2nd floor, ask for DC group"). Separate from the structured `venue` object above.

    • startDate string

      Start date (ISO 8601)

    • endDate string

      End date (ISO 8601)

    • ticketsEnabled boolean

      Whether tickets are available

    • rsvpEnabled boolean

      Whether RSVP is available

  • nextCursor string

    Cursor for the next page, or `null` if no more events.

GET /events/:eventID — Get event details

Returns full details for a specific event, including your ticket status.

Path parameters

  • eventID e.g. sWnllj1DW2jLMZ1n2KWB

    The event ID

Response

  • event object

    Full event details

  • myTickets object[]

    Your tickets for this event (empty array if none)

GET /events/:eventID/attendees — List event attendees

List the confirmed attendees of an event — DCers holding a `valid` paid ticket OR a `valid`/`maybe` RSVP status. Refunded/canceled tickets are excluded. Hidden and guest profiles are filtered out. Profiles returned use the same shape as the rest of the API (`GET /profile-match`, `GET /trips/:tripID/discovery`, etc.) — full public-other-person view including bizName, socials, expertise, plus privacy-gated revenue + teamSize where shared. **Access:** any active DCer can view event attendees, matching the in-app attendee tab.

Path parameters

  • eventID e.g. sWnllj1DW2jLMZ1n2KWB

    The event ID

Query parameters

  • limit number default: 100

    Max results (1-100).

Response

  • attendees object[]

    Array of attendee base profiles

    • userID string

      Member ID

    • userName string

      Username (handle)

    • displayName string

      Display name

    • photo string

      Profile photo URL

    • profileURL string

      Profile URL on DC

    • headline string

      Profile headline

    • industry string

      Business industry

    • joinedDate string

      Join date (YYYY-MM-DD)

  • total number

    Total attendee count

POST /events/:eventID/rsvp — RSVP to a free event

RSVP to an event that uses free RSVP (not ticketed). Only works for events with rsvpEnabled: true.

Path parameters

  • eventID e.g. sWnllj1DW2jLMZ1n2KWB

    The event ID

Request body

  • status string required

    RSVP status

    Values: yes, maybe, no

Response

  • rsvp object

    Your RSVP record

GET /events/:eventID/schedule — Get event schedule

Returns the full schedule (sessions) for an event, sorted chronologically. **Access:** any active DCer who can see the event can view its public schedule. Personal agenda actions still require a valid ticket. **Time-zone handling:** session `startAt` / `endAt` are returned as ISO 8601 strings whose digits represent the **venue-local wall-clock time** (e.g. a 9 AM Mexico City session returns `2026-05-08T09:00:00.000Z`, NOT `15:00:00Z`). The session's `timezone` field carries the IANA zone (e.g. `America/Mexico_City`) — pair them when localizing. This matches the convention used by the DC ICS feed.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

Response

  • sessions object[]

    Sessions in chronological order. `date` is YYYY-MM-DD (venue-local) for day-grouping; `startAt`/`endAt` are wall-clock ISO strings + `timezone` for full localization.

    • sessionID string

      Session ID

    • title string

      Title

    • description string

      Description (markdown)

    • date string

      Date YYYY-MM-DD (venue-local — used to group sessions by day)

    • startAt string

      Start time as wall-clock ISO 8601 (digits are venue-local; pair with `timezone`)

    • endAt string

      End time as wall-clock ISO 8601 (digits are venue-local; pair with `timezone`)

    • timezone string

      IANA timezone of the venue (e.g. America/Mexico_City)

    • type string

      Session type

      Values: mainstage, talk, workshop, discussion, meetup, mastermind, social, morning, break, other

    • speakers object[]

      Speakers — array of `{ userID, name, photoURL, bio }`

    • themes string[]

      Topic tags

    • audience string

      One-line "who is this for"

    • capacity number

      Capacity override (null = use venue default)

    • rsvpCount number

      Number of attendees who bookmarked this session

    • venueID string

      Venue ID at the event (or null for off-site sessions)

    • place object

      Off-site place (when locationType=place)

    • locationNote string

      Free-text location label (when locationType=note)

    • locationType string

      Location source

      Values: venue, place, note

    • spansAllVenues boolean

      True if the session spans every venue (general assembly, etc.)

  • timezone string

    IANA timezone of the event venue

GET /events/:eventID/agenda — Get your personal agenda for an event

Returns the sessions and meetups **YOU** have on your personal agenda for an event: - Sessions you bookmarked from the schedule. - Meetups you RSVPd to. **Access:** caller must hold a valid ticket to the event. Use `POST /events/:eventID/schedule/:sessionID/bookmark` and `POST /events/:eventID/meetups/:meetupID/rsvp` to manage entries.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

Response

  • sessions object[]

    Sessions you have bookmarked, in chronological order. Same per-item shape as `/schedule`.

  • meetups object[]

    Meetups you have RSVPd to, in chronological order. Same per-item shape as `/meetups`.

  • timezone string

    IANA timezone of the event venue

GET /events/:eventID/agenda/:userID — Get another attendee's agenda for an event

Returns another attendee's personal agenda for an event — the sessions they bookmarked + meetups they RSVPd to. Use this so an AI agent can plan together with another DCer (find a coffee window, suggest sessions to overlap, propose a meetup). **Auth**: ticket-holder ↔ ticket-holder. Both you and the target must hold a valid ticket to the event.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

  • userID e.g. 1673

    Target attendee userID

Response

  • profile object

    Mini profile of the target attendee

    • userID string

      Member ID

    • userName string

      Username (handle)

    • displayName string

      Display name

    • photo string

      Profile photo URL

    • profileURL string

      Profile URL on DC

    • headline string

      Profile headline

  • sessions object[]

    Sessions they have bookmarked, chronological order

  • meetups object[]

    Meetups they have RSVPd to, chronological order

  • timezone string

    IANA timezone of the event venue

GET /events/:eventID/schedule/:sessionID/attendees — List session attendees (people who bookmarked it)

Returns the list of attendees who have **bookmarked** a specific session into their agenda. Same profile shape as `/events/:eventID/attendees`. **Access:** caller must hold a valid ticket to the event.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

  • sessionID e.g. session_abc123

    Session ID

Response

  • attendees object[]

    Attendees who have this session in their agenda

  • total number

    Total attendee count for this session

GET /events/:eventID/meetups — List event meetups

Returns the approved member-organized meetups for an event, sorted chronologically. Only approved meetups are returned. **Access:** any active DCer who can see the event can view approved meetup listings. RSVP and attendee lists still require a valid ticket. **Time-zone handling:** meetups use explicit wall-clock fields (`date` = YYYY-MM-DD, `startTime` / `endTime` = HH:mm) plus the event's `timezone` (IANA). Pair them when localizing.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

Response

  • meetups object[]

    Approved meetups in chronological order

    • meetupID string

      Meetup ID

    • title string

      Title

    • shortDescription string

      Short description (one-line)

    • description string

      Long description (markdown)

    • date string

      Date YYYY-MM-DD (venue-local)

    • startTime string

      Start time HH:mm (venue-local)

    • endTime string

      End time HH:mm (venue-local)

    • timezone string

      IANA timezone of the event

    • maxSeats number

      Maximum attendees

    • rsvpCount number

      Current RSVP count

    • host object

      Host (the member organizing the meetup)

    • venue object

      Meeting venue (Place — name, city, country, placeID)

    • venueDetails string

      Free-text venue details (e.g. "ask for DC group")

  • timezone string

    IANA timezone of the event venue

GET /events/:eventID/meetups/:meetupID/attendees — List meetup attendees

Returns the list of attendees who have RSVPd to a specific meetup. Same profile shape as `/events/:eventID/attendees`. **Access:** caller must hold a valid ticket to the event.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

  • meetupID e.g. meetup_xyz789

    Meetup ID

Response

  • attendees object[]

    Attendees who RSVPd to this meetup

  • total number

    Total RSVP count

GET /events/:eventID/sponsors — List event sponsors

Returns the sponsors for an event, ordered by tier (primary → supporting) then display order. Deleted sponsors are filtered out. **Access:** caller must hold a valid ticket to the event.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

Response

  • sponsors object[]

    Sponsors in display order (tier first, then `order` within tier)

    • sponsorID string

      Sponsor ID

    • name string

      Sponsor name

    • logoURL string

      Logo image URL

    • websiteURL string

      Marketing website URL

    • description string

      Description (markdown)

    • tier string

      Sponsorship tier

      Values: primary, supporting

POST /events/:eventID/schedule/:sessionID/bookmark — Bookmark / unbookmark a session

Add or remove a session from your personal agenda — this is the API equivalent of the bookmark/star icon on a session card in the DC app. Requires a valid ticket for the event. Counter `rsvpCount` on the session doc is updated atomically and idempotently: repeating the same desired state does not increment or decrement the counter again.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

  • sessionID e.g. session_abc123

    Session ID

Request body

  • bookmarked boolean required

    `true` to add to agenda, `false` to remove

Response

  • bookmarked boolean

    Final bookmark state on your agenda

POST /events/:eventID/meetups/:meetupID/rsvp — RSVP to / leave a meetup

Join or leave a meetup. Requires a valid ticket for the event. The meetup's `rsvpCount` is updated atomically and idempotently. When the meetup has a linked chat channel, this mirrors the DC app side effects too: joining subscribes you to the meetup chat and leaving removes you from it.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

  • meetupID e.g. meetup_xyz789

    Meetup ID

Request body

  • joined boolean required

    `true` to join, `false` to leave

Response

  • joined boolean

    Final RSVP state

  • rsvpCount number

    Current RSVP count for this meetup (after your change)

GET /events/:eventID/agendas — Get multiple attendees' agendas in one call

Returns the agendas (bookmarked sessions + meetup RSVPs) for **multiple** attendees in a single call. Use when an AI agent needs to plan around several DCers at once — comparing schedules, finding shared sessions, building a meetup invite list. **Query**: `userIDs=A,B,C` — comma-separated. Max 20 IDs per call. **Behavior**: silently drops IDs that don't hold a valid ticket (so the AI doesn't need to pre-filter). Returns only the agendas for confirmed attendees, in the order requested. **Auth**: caller must hold a valid ticket to the event.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

Query parameters

  • userIDs string required

    Required. Comma-separated userIDs (max 20). Non-attendees are silently dropped.

Response

  • agendas object[]

    One entry per confirmed attendee, in the order requested

    • userID string

      Attendee userID

    • profile object

      Mini profile of the attendee

    • sessions object[]

      Sessions they bookmarked (chronological)

    • meetups object[]

      Meetups they RSVPd to (chronological)

  • timezone string

    IANA timezone of the event venue

POST /events/:eventID/free-slots — Find shared free time slots across attendees

Computes shared **free slots** across a set of event attendees — the time windows where they're NOT in a bookmarked session or meetup. Use to find a coffee window with one DCer, or a junto-style lunch slot for a group. **Body**: `userIDs[]` (1-20), `minDurationMins` (default 30, min 15, max 480), optional `withinDayDate: YYYY-MM-DD` to scope to a single event day. **Slot grid**: derived from the event's session schedule, partitioned into `minDurationMins` windows. For each window we subtract each user's bookmarked sessions + meetup RSVPs. **Sort**: slots ranked by `len(freeFor)` desc — fully-shared windows first, then partial overlaps. **Auth**: caller must hold a valid ticket. Non-attendee IDs are silently dropped.

Path parameters

  • eventID e.g. BbZlk82DNQFbV4HT2nJo

    Event ID

Request body

  • userIDs string[] required

    Attendee userIDs to compare (1-20). Non-attendees silently dropped.

  • minDurationMins number

    Minimum slot duration in minutes (default 30, range 15-480)

  • withinDayDate string

    Optional. Scope to a single event day (YYYY-MM-DD venue-local). Omit for the full event range.

Response

  • slots object[]

    Free slots ranked by overlap (most-shared first). Wall-clock + IANA timezone — same convention as `/schedule`.

    • startAt string

      Slot start (wall-clock ISO)

    • endAt string

      Slot end (wall-clock ISO)

    • durationMins number

      Duration in minutes

    • timezone string

      IANA timezone of the event venue

    • freeFor string[]

      userIDs free during this slot

    • busyFor string[]

      userIDs busy (bookmarked session or meetup) during this slot

  • timezone string

    IANA timezone of the event venue

Virtual Events

GET /virtual-events — List virtual events

Returns upcoming virtual events (online sessions like Connect Calls, Happy Hour, Welcome Call, plus DC BLACK-only events). Add `?past=true` to include past events.

Query parameters

  • past boolean default: false

    Include past events.

  • limit number default: 20

    Max results (1-100).

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • events object[]

    Array of virtual events

    • sessionID string

      Session ID

    • name string

      Event name

    • kind string

      Session kind

      Values: dc, dcb, dca, welcome, happy, virtual

    • description string

      Event description

    • scheduledAt string

      Scheduled start (ISO 8601)

    • scheduledEndAt string

      Scheduled end (ISO 8601)

    • duration number

      Duration in minutes

    • attendeeCount number

      Number of attendees

    • isLive boolean

      Whether the event is currently live

    • myRsvp string

      Your RSVP (null if none)

      Values: yes, no, maybe

    • meetUrl string

      Meet/video URL (if you RSVPd yes/maybe)

  • nextCursor string

    Cursor for the next page, or `null` if no more events.

GET /virtual-events/:sessionID — Get virtual event details

Returns the same payload shape as one entry from `GET /virtual-events` for a single online session — `sessionID`, `name`, `description`, `kind` (which audience tier the session is open to), `scheduledAt` / `scheduledEndAt` (ISO 8601), `duration` in minutes, `attendeeCount`, `isLive`, `meetUrl` (the video-call join link, returned regardless of your RSVP state), `myRsvp` (your current `yes`/`no`/`maybe` or `null`), and `status`. DC BLACK callers also see DC BLACK-only sessions; DC tier callers get `tier_restricted` (403) on those.

Path parameters

  • sessionID e.g. abc123

    The virtual session ID. Find IDs via `GET /virtual-events`.

Response

  • event object

    Virtual event details. Same shape as one entry from `GET /virtual-events`.

    • sessionID string

      Session ID

    • name string

      Event name

    • kind string

      Session kind

      Values: dc, dcb, dca, welcome, happy, virtual

    • description string

      Event description

    • scheduledAt string

      Scheduled start (ISO 8601)

    • scheduledEndAt string

      Scheduled end (ISO 8601)

    • duration number

      Duration in minutes

    • attendeeCount number

      Number of attendees who RSVPd yes

    • isLive boolean

      Whether the event is currently live

    • myRsvp string

      Your RSVP, or `null` if you haven't RSVPd

      Values: yes, no, maybe

    • meetUrl string

      Video-call join URL. Returned regardless of your RSVP state when the host has set one.

    • status string

      Session lifecycle status

POST /virtual-events/:sessionID/rsvp — RSVP to virtual event

RSVP to a virtual (online) event. The user is added to the matching attendance list on the session doc (`participantIDs` for `yes`, `maybeIDs` for `maybe`, `notIDs` for `no`) and removed from the others. Three statuses: - `yes` — you intend to attend; you'll show up in `attendeeCount`. - `maybe` — soft attendance signal. - `no` — you're declining. Use this to back out after a prior `yes` or `maybe`. **Note:** the `meetUrl` (join link) on `GET /virtual-events/:sessionID` is **not** gated on your RSVP — it's returned whenever the host has set one, regardless of attendance state. RSVPing is purely an attendance signal. **Idempotent** — re-RSVPing with the same status is a no-op.

Path parameters

  • sessionID e.g. abc123

    The virtual session ID. Find IDs via `GET /virtual-events`.

Request body

  • status string required

    Your RSVP status for this session.

    Values: yes, maybe, no

Response

  • rsvp object

    Echo of the accepted RSVP. Re-fetch `GET /virtual-events/:sessionID` if you need the post-RSVP attendee count or other derived state.

    • sessionID string

      The session you RSVPd to.

    • status string

      Your applied status — `yes`, `maybe`, or `no`.

      Values: yes, maybe, no

    • userID string

      Your userID (echoed).

Tickets

GET /tickets — List your tickets

Returns your tickets across events, newest first. Defaults to the tickets you're holding (`valid` plus `maybe`) — "what am I attending". Pass `?status=valid`, `?status=maybe`, or `?status=refunded` to narrow to one.

Query parameters

  • status string default: valid,maybe

    Filter by a single ticket status. With no value, returns the tickets you're holding (`valid` and `maybe`). `refunded` is available on request.

  • limit number default: 50

    Max results (1-100).

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • tickets object[]

    Array of tickets

    • ticketID string

      Ticket ID

    • eventID string

      Event ID

    • eventName string

      Event name

    • eventType string

      Event type

    • eventURL string

      Link to event on DC (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same event.

    • status string

      Ticket status

      Values: valid, maybe, refunded

    • ticketName string

      Ticket name (e.g. "General Admission")

    • ticketSlug string

      Ticket slug

    • startDate string

      Event start date (ISO 8601)

    • endDate string

      Event end date (ISO 8601)

    • paidAt string

      Purchase date (ISO 8601)

  • nextCursor string

    Cursor for the next page, or `null` if no more tickets.

Example: List your valid tickets

{
  "data": {
    "tickets": [
      {
        "endDate": "2026-04-17T00:00:00.000Z",
        "eventID": "evt456",
        "eventName": "DCBKK 2026",
        "eventType": "dcbkk",
        "paidAt": "2026-02-15T10:30:00.000Z",
        "startDate": "2026-04-10T00:00:00.000Z",
        "status": "valid",
        "ticketID": "tkt789",
        "ticketName": "General Admission",
        "ticketSlug": "general-admission"
      }
    ]
  },
  "ok": true
}

Invites

GET /invites — List your invites

List the referral invites credited to you. Two source types appear: - **`manual`** — invites you sent via `POST /invites` (the explicit email-an-invitee flow). - **`permaCode`** — applicants who signed up through your shareable permacode link (`GET /invites/permacode`). Each record tracks where the prospective member is in the funnel (`new` → `invited` → `started` → `submitted` → `approved`/`rejected`/`expired`), the invite type, the invitee's name + email, and timestamps. Read-only.

Query parameters

  • limit number default: 50

    Max results (1-100).

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • invites object[]

    Array of invite records

    • inviteID string

      Invite ID

    • status string

      Where the invitee is in the application funnel. Main happy-path values: `new` → `invited` → `started` → `submitted` → `approved`. Other terminal/exception states: `booked-call` (intro call scheduled), `awaiting-payment-auth` (approved, awaiting payment confirmation), `qualified` (passed screening, not yet approved), `rejected`, `invalid`, `expired`.

      Values: new, invited, started, booked-call, awaiting-payment-auth, submitted, approved, rejected, invalid, qualified, expired

    • type string

      Invite type. Main values: `manual` (you sent it via `POST /invites`) and `permaCode` (applicant signed up via your shareable link). `mention` may also appear when an applicant mentioned you by name on their form — not reliable, don't count on it.

      Values: manual, permaCode, mention

    • fullName string

      Invitee full name

    • email string

      Invitee email

    • permaCode string

      Permanent invite code (for permaCode invites)

    • createdAt string

      Created date (ISO 8601)

    • expiresAt string

      Expiration date (ISO 8601)

  • nextCursor string

    Cursor for the next page, or `null` if no more invites.

POST /invites — Send an invite

Send a referral invite to someone. The server queues a templated email (delivered via a background task) that points the invitee at the apply flow with you pre-credited as the referrer. The created invite shows up in `GET /invites` immediately at status `new`.

Request body

  • fullName string required

    Invitee full name. Used in the email greeting + matched against existing applications for dedup.

  • email string required

    Invitee email address. Where the invite email is sent.

  • whyDC string

    Optional. Short note about why they would be a good fit for DC — surfaces in the admin review queue if the application reaches it.

Response

  • invite object

    The created invite. **Note:** the create shape differs from list-entry shape — fields nest under `referral`. Fetch `GET /invites` for the full enriched record after the invitee starts the funnel.

    • referralID string

      Invite ID (matches the `inviteID` field on `GET /invites`).

    • status string

      Always `new` on create. Tracks where the invitee is in the funnel — see `GET /invites` for the full enum.

      Values: new

    • type string

      Always `manual` on create — invites you send explicitly via this endpoint.

      Values: manual

    • createdAt string

      ISO 8601 — when the invite was created.

    • referral object

      Nested invitee details.

      • email string

        Invitee email.

      • fullName string

        Invitee full name.

GET /invites/permacode — Get your permacode

Returns your permanent referral code. Share this link to let people apply with your referral.

Response

  • permaCode string

    Your permanent referral code

  • referralURL string

    Full referral URL

Inbox

GET /inbox/unread — Get unread counts

Returns your total unread message count and per-room breakdown. Only includes rooms you are subscribed to or are a member of.

Query parameters

  • limit number default: 50

    Max rooms to return (1-100).

Response

  • totalUnread number

    Total unread messages across all rooms

  • rooms object[]

    Per-room unread counts

    • roomID string

      Room ID

    • roomName string

      Room name

    • roomType string

      Room type (`channel`, `dm`, `group`, `discussion`, `quick-question`, `event`).

    • roomURL string

      Permalink to the room (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same room — equivalent destination, shorter for display / sharing.

    • badgeCount number

      Unread message count for this room

Example: Check unread messages

{
  "data": {
    "rooms": [
      {
        "badgeCount": 5,
        "roomID": "room1",
        "roomName": "General",
        "roomType": "channel",
        "roomURL": "https://dc.dynamitecircle.com/channel/room1"
      },
      {
        "badgeCount": 7,
        "roomID": "room2",
        "roomName": "Jane Doe",
        "roomType": "dm",
        "roomURL": "https://dc.dynamitecircle.com/inbox/room2"
      }
    ],
    "totalUnread": 12
  },
  "ok": true
}

Rooms

GET /rooms — List your subscribed rooms

Returns every room you are subscribed to (DMs, group DMs, channels you follow, discussions, activities, event rooms), sorted by `lastActivityAt` descending. Cursor-paginated. To filter by type use `GET /rooms/inbox/:type` (e.g. `/rooms/inbox/dm` for DMs only).

Query parameters

  • limit number default: 50

    Max results (1-100)

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • rooms object[]

    Array of rooms

    • roomID string

      Room ID

    • type string

      Room type. `dm` = one-on-one direct messages. `group` = group DMs. `quick-question` = the "Quick Question" rooms in the app.

      Values: channel, dm, group, discussion, quick-question, event

    • roomURL string

      Link to room on DC (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same room — equivalent destination, shorter for display / sharing.

    • scope string

      Community scope

      Values: dc, dcb

    • name string

      Room name

    • description string

      Room description

    • lastActivityAt string

      Last activity timestamp (ISO 8601)

    • stats object

      Room stats

      • comments number

        Total comments

      • reactions number

        Total reactions

      • subscribers number

        Subscriber count

  • nextCursor string

    Cursor for the next page (or `null` if no more rooms).

GET /rooms/inbox/:type — List your rooms by type

Returns your subscribed rooms filtered to a single type. Same shape as `GET /rooms` but scoped — e.g. `/rooms/inbox/dm` returns DMs only, `/rooms/inbox/group` returns group DMs.

Path parameters

  • type e.g. dm

    Room type filter. Allowed: `channel`, `dm`, `group`, `discussion`, `quick-question`, `event`.

Query parameters

  • limit number default: 50

    Max results (1-100)

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • rooms object[]

    Array of rooms (same shape as `GET /rooms`)

  • nextCursor string

    Cursor for the next page (or `null` if no more rooms).

GET /rooms/browse/:type — Browse public channels by type

Browse publicly-joinable rooms of a given type that you are NOT yet subscribed to. The same surface the in-app Browse Channels modal shows. DC BLACK rooms are filtered out for DC tier members.

Path parameters

  • type e.g. channel

    Room type to browse. Allowed: `channel`, `discussion`, `quick-question`.

Query parameters

  • limit number default: 50

    Max results (1-100)

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • rooms object[]

    Array of browsable rooms

  • nextCursor string

    Cursor for the next page (or `null` if no more rooms).

GET /rooms/:roomID — Get a single room

Get a single room's metadata + its latest daily AND weekly AI summaries (when they exist). **Access:** members and subscribers of the room, plus any DCer for browsable public channels/discussions/quick-questions. Private rooms, DMs, group DMs, and event/city rooms you are not a member of return 403. Reading this endpoint does **not** mark the room as read or modify any unread state. **AI summaries:** the latest daily digest is embedded under `aiSummaryDaily`, the latest weekly digest under `aiSummaryWeekly`. Rooms that don't have a given type yet return `null` for that slot. For history (older summaries), call `GET /rooms/:roomID/summaries/daily` or `/weekly`. **See also:** For specific content (`did anyone mention X?`), `POST /search/messages` with `q=` and `roomID=` is faster than paginating `/rooms/:roomID/messages` or reading summaries. The AI summaries cover broad activity per window; search is the tool for targeted lookup.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • room object

    Room object (same shape as `GET /rooms` array entries)

  • aiSummaryDaily object

    Latest daily AI summary, or `null` if the room has no daily summaries yet.

    • summaryID string

      Summary doc ID (the date for daily summaries, the week ID for weekly).

    • type string

      Kind of summary.

      Values: daily, weekly

    • html string

      Sanitized HTML body — safe to render inside a card. Contains links, mentions, emoji, and basic formatting.

    • topics object[]

      Topic tags surfaced from the summary.

    • urls object[]

      URLs shared during the window, each `{ label, url, sharedBy }`.

    • intervalStartAt string

      ISO 8601 — start of the window this summary covers.

    • intervalEndAt string

      ISO 8601 — end of the window this summary covers.

    • generatedAt string

      ISO 8601 — when the AI generated this summary.

    • messageCount number

      Total messages in the window.

    • participantCount number

      Distinct participants in the window.

  • aiSummaryWeekly object

    Latest weekly AI summary, or `null` if the room has no weekly summaries yet.

    • summaryID string

      Summary doc ID (the date for daily summaries, the week ID for weekly).

    • type string

      Kind of summary.

      Values: daily, weekly

    • html string

      Sanitized HTML body — safe to render inside a card. Contains links, mentions, emoji, and basic formatting.

    • topics object[]

      Topic tags surfaced from the summary.

    • urls object[]

      URLs shared during the window, each `{ label, url, sharedBy }`.

    • intervalStartAt string

      ISO 8601 — start of the window this summary covers.

    • intervalEndAt string

      ISO 8601 — end of the window this summary covers.

    • generatedAt string

      ISO 8601 — when the AI generated this summary.

    • messageCount number

      Total messages in the window.

    • participantCount number

      Distinct participants in the window.

GET /rooms/:roomID/summary/:type — Get the latest daily or weekly summary

Get the latest single summary of a given type for a room. **Type is required** — daily and weekly summaries cover different windows and live in separate slots. Pass the type you want as a path segment. For history (multiple past summaries) use `GET /rooms/:roomID/summaries/:type`. Same access gate as `GET /rooms/:roomID`. **See also:** AI summaries cover broad activity per window. For specific content (`did anyone mention X?`), `POST /search/messages` with `q=` and `roomID=` is faster than reading summaries.

Path parameters

  • roomID e.g. abc123

    Room ID

  • type e.g. daily

    Summary type — `daily` or `weekly`.

Response

  • aiSummary object

    Latest summary of the requested type, or `null` if none exist yet.

    • summaryID string

      Summary doc ID (the date for daily summaries, the week ID for weekly).

    • type string

      Kind of summary.

      Values: daily, weekly

    • html string

      Sanitized HTML body — safe to render inside a card. Contains links, mentions, emoji, and basic formatting.

    • topics object[]

      Topic tags surfaced from the summary.

    • urls object[]

      URLs shared during the window, each `{ label, url, sharedBy }`.

    • intervalStartAt string

      ISO 8601 — start of the window this summary covers.

    • intervalEndAt string

      ISO 8601 — end of the window this summary covers.

    • generatedAt string

      ISO 8601 — when the AI generated this summary.

    • messageCount number

      Total messages in the window.

    • participantCount number

      Distinct participants in the window.

GET /rooms/:roomID/summaries/:type — List past daily or weekly summaries

List past summaries of a given type for a room, newest first. Cursor-paginated — pass `cursor` from the previous response to fetch the next (older) page. Each summary covers a non-overlapping window (one per day for daily, one per week for weekly). Use this for catch-up workflows ("show me the last 7 daily summaries before I rejoin the conversation"). Same access gate as `GET /rooms/:roomID`. **See also:** Summaries cover broad activity per window. For specific content (`did anyone mention X?`), `POST /search/messages` with `q=` and `roomID=` is faster than reading multiple summaries.

Path parameters

  • roomID e.g. abc123

    Room ID

  • type e.g. daily

    Summary type — `daily` or `weekly`.

Query parameters

  • limit number default: 20

    Max results (1-50)

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next (older) page.

Response

  • summaries object[]

    Array of summaries of the requested type, newest first.

    • summaryID string

      Summary doc ID (the date for daily summaries, the week ID for weekly).

    • type string

      Kind of summary.

      Values: daily, weekly

    • html string

      Sanitized HTML body — safe to render inside a card. Contains links, mentions, emoji, and basic formatting.

    • topics object[]

      Topic tags surfaced from the summary.

    • urls object[]

      URLs shared during the window, each `{ label, url, sharedBy }`.

    • intervalStartAt string

      ISO 8601 — start of the window this summary covers.

    • intervalEndAt string

      ISO 8601 — end of the window this summary covers.

    • generatedAt string

      ISO 8601 — when the AI generated this summary.

    • messageCount number

      Total messages in the window.

    • participantCount number

      Distinct participants in the window.

  • nextCursor string

    Cursor for the next (older) page, or `null` if no older summaries.

GET /rooms/:roomID/messages — List messages in a room

List messages in a room you are a member of. **Read-only — no write side effects, no unread-state mutation, no reactions/posts/edits.** Cursor-paginated newest-first. **Access:** strict — the caller must be a subscribed member of the room (same `seen` doc check used by the web inbox). For browsable public channels, any DCer can read. Private rooms, DMs (`dm`), group DMs (`group`), event rooms, and city/country/mastermind rooms hard-block non-members with 403. Hidden/deleted/sunk messages are excluded. **Pagination:** pass `?before=<nextCursor>` from a previous response to fetch the next (older) page. Default page size 50, max 100. **See also:** For specific content in this room (`did anyone mention X?`), `POST /search/messages` with `q=` and `roomID=` searches body text directly — far faster than paginating with `?before`. This endpoint is the right call when you want a chronological window (last N messages, conversation reconstruction); search is the right call when you want a topic.

Path parameters

  • roomID e.g. abc123

    Room ID. Discover from `GET /rooms` (your subscribed list), `GET /inbox/unread`, `trip.roomID` on `GET /trips/:tripID`, or event chat-room IDs on `GET /events/:eventID`.

Query parameters

  • limit number default: 50

    Max results (1-100)

  • before string default:

    Cursor from a previous response's `nextCursor` (encodes the previous page's oldest message timestamp). Pass to fetch the next older page.

Response

  • messages object[]

    Array of messages, newest-first.

    • messageID string

      Message ID

    • roomID string

      Room ID this message belongs to

    • sentAt string

      When the message was sent (ISO 8601)

    • editedAt string

      When the message was last edited (ISO 8601), or `null` if never edited

    • isDeleted boolean

      Whether the message has been deleted by its author or an admin. Deleted messages still appear as tombstones with empty `text`.

    • author object

      Mini profile of the author (`null` for system messages).

      • userID string

        User ID

      • userName string

        Handle / username slug

      • displayName string

        Display name

      • photo string

        Avatar URL

      • profileURL string

        Profile URL on DC

    • text string

      Message body. For text messages this is the rendered source (may contain sanitized HTML — links, mentions, emoji). For image/file/video messages this is the optional caption (often empty). For system messages this is the system-generated text.

    • type string

      Message kind: `text`, `image`, `file`, `video`, `system`, `custom`, `textStream`.

    • isHTML boolean

      When the message contains rich content, `true`. Plain-text messages without formatting are `false`.

    • replyTo object

      Reply target — `null` unless this message replies to another in the same room.

      • messageID string

        Message ID of the parent (replied-to) message

    • reactions object

      Emoji reactions on the message. Map of emoji key → count.

  • nextCursor string

    Cursor for the next (older) page (or `null` if no older messages).

POST /rooms/:roomID/subscribe — Subscribe to a room

Subscribe to a public channel, discussion, quick-question room, or event room. The caller is added to the room's `seen` subcollection with `flags.isSubscribed: true` and starts receiving its updates in their inbox. **Access:** the room must be enabled, non-archived, non-private, non-hidden, and of a subscribable type (`channel`, `discussion`, `quick-question`, `event`). Event rooms additionally require a valid ticket to the linked event — call `/events/:eventID` first to verify ticket status. DMs and group DMs cannot be subscribed/unsubscribed via the API; they are managed in-app only. **Idempotent:** subscribing when already subscribed is a no-op (returns 200 with the current state).

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/unsubscribe — Unsubscribe from a room

Unsubscribe from a public channel, discussion, quick-question, or event room. The caller's `seen` doc is updated to `flags.isSubscribed: false`, the badge count is cleared, and the room drops out of the inbox sidebar. **Access:** the caller must already be a subscriber. DMs and group DMs cannot be unsubscribed via the API. **Idempotent:** unsubscribing when already unsubscribed is a no-op.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/mute — Mute a room

Mute notifications for a room. Sets `mutedUntilAt` to a far-future timestamp (no expiry) — the room stays muted until explicitly unmuted. The room still appears in the inbox; only notifications are suppressed. **Access:** the caller must be a member/subscriber of the room.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/unmute — Unmute a room

Unmute a previously-muted room. Clears `mutedUntilAt`. **Access:** the caller must be a member/subscriber of the room. Idempotent.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/archive — Archive a room

Archive a room — hides it from the inbox sidebar without unsubscribing. Use `unarchive` to bring it back. **Access:** the caller must be a member/subscriber. Idempotent.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/unarchive — Unarchive a room

Unarchive a previously-archived room. Restores it to the inbox sidebar. **Access:** the caller must be a member/subscriber. Idempotent.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/pin — Pin a room

Pin a room to the top of the inbox. For subscription-type rooms the caller is auto-subscribed if not already (mirrors the in-app behavior — you can't pin what you don't follow). **Access:** the caller must already have an interaction history with the room (DMs and group DMs require having received at least one message). Idempotent.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

POST /rooms/:roomID/unpin — Unpin a room

Unpin a previously-pinned room. Returns it to its normal place in the inbox sort order. **Access:** the caller must be a member/subscriber. Idempotent.

Path parameters

  • roomID e.g. abc123

    Room ID

Response

  • seen object

    Echo of the updated subscription state. Boolean flags + ISO timestamps.

    • isSubscribed boolean

      True when subscribed to this room (channels / discussions / quick-questions / event rooms).

    • isArchived boolean

      True when archived (hidden from the inbox sidebar but still searchable).

    • isPinned boolean

      True when pinned to the top of the inbox.

    • isMuted boolean

      True when notifications are muted (mutedUntilAt is in the future).

    • lastSeenAt string

      ISO 8601 — when the caller last marked the room read.

    • subscribedAt string

      ISO 8601 — when the caller most recently subscribed.

    • unsubscribedAt string

      ISO 8601 — when the caller most recently unsubscribed.

    • mutedUntilAt string

      ISO 8601 — when notifications stay muted until (`null` = not muted).

    • archivedAt string

      ISO 8601 — when the room was last archived.

    • unarchivedAt string

      ISO 8601 — when the room was last unarchived.

    • pinnedAt string

      ISO 8601 — when the room was pinned (`null` = not pinned).

Locator

GET /locator/digest — Get locator digest

Returns your weekly locator digest — the same data that powers the Friday locator email. Use this to surface trip/event activity around the people and cities a member already follows. The response is composed of four independent sections; pass `?sections=<csv>` to skip any you don't need. Each section is described in full below. - **`homeCity`** — Activity in the city you have set as your home chapter. Null if you have no home city, or if you don't belong to any chapter yet. - **`favoriteCities`** — Per-city digest for cities you have favorited (besides your home city). Each entry lists upcoming trips/events into that city + new ones added since last week. - **`favoritePeople`** — Recent activity from members you follow: their new trips, upcoming trips, recently purchased tickets, and events they've RSVPd to. - **`myTrips`** — For each of your own upcoming trips, the people you're likely to overlap with (chapter leads, local members, and other DCers visiting the same city in the same window). Pass a comma-separated subset to `?sections=...` to omit sections you don't use — useful for narrow integrations and faster responses.

Query parameters

  • sections string

    Comma-separated list of sections to include. Defaults to all four sections when omitted.

Response

  • homeCity object

    Activity in your home chapter's city. `null` if you don't have a home city set, or if your profile is not associated with any chapter.

    • cityID string

      Google Place ID of the home city

    • cityName string

      Home city name

    • comingToCity object[]

      Members visiting your home city soon (their trips overlap with you here).

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • planningToCity object[]

      Members planning future trips into your home city (further out).

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • comingEvents object[]

      Upcoming events happening in your home city.

      • eventID string

        Event ID

      • name string

        Event name

      • eventType string

        Event type

      • eventURL string

        Link to the event page on DC (canonical host).

      • shortURL string

        Branded short link (dc.mba) to the same event.

      • startDate string

        Event start date (ISO 8601)

      • endDate string

        Event end date (ISO 8601)

      • city object

        Host city

        • name string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • placeID string

          Google Place ID

    • createdEvents object[]

      Events you have created or are hosting in this city.

      • eventID string

        Event ID

      • name string

        Event name

      • eventType string

        Event type

      • eventURL string

        Link to the event page on DC (canonical host).

      • shortURL string

        Branded short link (dc.mba) to the same event.

      • startDate string

        Event start date (ISO 8601)

      • endDate string

        Event end date (ISO 8601)

      • city object

        Host city

        • name string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • placeID string

          Google Place ID

    • newMembers object[]

      Members who have recently joined your home chapter.

      • userID string

        Member ID

      • userName string

        DC username (used in profile URL)

      • displayName string

        Display name

      • photo string

        Profile photo URL

      • profileURL string

        Link to the member's public profile on DC

  • favoriteCities object[]

    Per-city digest for each city you have favorited. Excludes your home city. Order is server-defined (typically by upcoming activity).

    • cityID string

      Google Place ID of the city

    • cityName string

      City name

    • country string

      Country

    • countryCode string

      ISO country code

    • comingTrips object[]

      Members with active or upcoming trips into this city.

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • newTrips object[]

      Trips into this city that were newly added since your last digest.

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • comingEvents object[]

      Events upcoming in this city.

      • eventID string

        Event ID

      • name string

        Event name

      • eventType string

        Event type

      • eventURL string

        Link to the event page on DC (canonical host).

      • shortURL string

        Branded short link (dc.mba) to the same event.

      • startDate string

        Event start date (ISO 8601)

      • endDate string

        Event end date (ISO 8601)

      • city object

        Host city

        • name string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • placeID string

          Google Place ID

    • newEvents object[]

      Events newly added in this city since your last digest.

      • eventID string

        Event ID

      • name string

        Event name

      • eventType string

        Event type

      • eventURL string

        Link to the event page on DC (canonical host).

      • shortURL string

        Branded short link (dc.mba) to the same event.

      • startDate string

        Event start date (ISO 8601)

      • endDate string

        Event end date (ISO 8601)

      • city object

        Host city

        • name string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • placeID string

          Google Place ID

  • favoritePeople object

    Activity from members you follow (favorited people). Each sub-array is independent — a member can appear in more than one.

    • newTrips object[]

      New trips your favorited people have added since the last digest.

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • comingTrips object[]

      Upcoming trips your favorited people have planned.

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • purchased object[]

      Tickets your favorited people have recently purchased.

      • eventID string

        Event ID the ticket is for

      • eventName string

        Event name

      • eventURL string

        Link to the event page on DC (canonical host).

      • shortURL string

        Branded short link (dc.mba) to the same event.

      • startDate string

        Event start date (ISO 8601)

      • endDate string

        Event end date (ISO 8601)

      • member object

        Member who owns the ticket

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

    • attending object[]

      Events your favorited people are attending (RSVPd).

      • eventID string

        Event ID the ticket is for

      • eventName string

        Event name

      • eventURL string

        Link to the event page on DC (canonical host).

      • shortURL string

        Branded short link (dc.mba) to the same event.

      • startDate string

        Event start date (ISO 8601)

      • endDate string

        Event end date (ISO 8601)

      • member object

        Member who owns the ticket

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

  • myTrips object[]

    For each of your own upcoming trips, the people you're likely to overlap with at the destination. Useful for "who can I meet on this trip" prompts.

    • trip object

      Your trip

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

    • cityID string

      Google Place ID of the trip's destination city

    • cityName string

      Destination city name

    • chapterLeads object[]

      DC chapter leads / city ambassadors for the destination city.

      • userID string

        Member ID

      • userName string

        DC username

    • localMembers object[]

      DC members who live in the destination city.

      • userID string

        Member ID

      • userName string

        DC username

    • plannedTrips object[]

      Other DCers planning trips that overlap with yours in this city/window.

      • tripID string

        Trip ID

      • startDate string

        Start date (ISO 8601)

      • endDate string

        End date (ISO 8601)

      • location object

        Destination location. Null if the trip has no resolved place.

        • city string

          City name

        • country string

          Country

        • countryCode string

          ISO country code

        • name string

          Display name (e.g. "Tokyo, Japan")

      • member object

        Trip owner — minimal profile info for linking. Always at least `{ userID }`.

        • userID string

          Member ID

        • userName string

          DC username (used in profile URL)

        • displayName string

          Display name

        • photo string

          Profile photo URL

        • profileURL string

          Link to the member's public profile on DC

      • note string

        Free-form note the trip owner attached to the trip.

Example: Fetch only home-city + people activity

{
  "sections": "homeCity,favoritePeople"
}
{
  "data": {
    "favoritePeople": {
      "attending": [],
      "comingTrips": [],
      "newTrips": [],
      "purchased": []
    },
    "homeCity": null
  },
  "ok": true
}

GET /locator/settings — Get your Friday locator email settings

Returns the four toggles that control the Friday locator email digest. The digest is a weekly outbound email surfacing new events, tickets, and trips relevant to you.

Response

  • locatorSettings object

    Friday locator email toggles

    • enabled boolean

      Master toggle for the Friday email digest

    • events boolean

      Include new events in your area

    • tickets boolean

      Include DCers you follow getting event tickets

    • trips boolean

      Include new trips to your area

Example: Default locator-email settings

{
  "data": {
    "locatorSettings": {
      "enabled": true,
      "events": true,
      "tickets": false,
      "trips": true
    }
  },
  "ok": true
}

PATCH /locator/settings — Update your Friday locator email settings

Update any subset of the Friday locator email toggles. Send only the fields you want to change.

Request body

  • enabled boolean

    Master toggle for the Friday digest

  • events boolean

    Include new events in your area

  • tickets boolean

    Include DCers you follow getting event tickets

  • trips boolean

    Include new trips to your area

Response

  • updated boolean

    `true` when the patch landed

Example: Disable the Friday locator email entirely

{
  "enabled": false
}
{
  "data": {
    "updated": true
  },
  "ok": true
}

Places

GET /places/:placeID — Get place details

Fetch full details for one Google Place ID. Useful for verifying a placeID before sending it to `POST /trips` (which only accepts `type: "city"` placeIDs and rejects venues with a 400). Same shape as a single entry from `GET /places/search`.

Path parameters

  • placeID e.g. ChIJ51cu8IcbXWARiRtXIothAS4

    Google Place ID. Get one from `GET /places/search` or from a previous response (e.g. `event.city.placeID`).

Response

  • place object

    Place details. Same shape as one entry from `GET /places/search`.

    • placeID string

      Google Place ID — pass to POST /trips (only when type=city) or to event APIs.

    • name string

      Display name.

    • type string

      Place type — `city` is usable in `POST /trips`; `venue` is usable in event/meetup APIs but rejected by trips.

      Values: city, venue

    • city string

      City (populated when the place resolves to a city; venues outside cities may be null).

    • country string

      Country.

    • countryCode string

      ISO country code.

    • region string

      Region / state / prefecture.

    • regionCode string

      Region short code.

    • description string

      Google formatted address — usable as a friendly display string.

    • lat number

      Latitude.

    • lon number

      Longitude.

    • latLon string

      "lat,lon" string.

    • locHash string

      Geohash for the location.

    • utcOffsetMins number

      UTC offset in minutes.

Chapters

GET /chapters — List chapters

List all DC chapters (city-based community hubs), sorted by member count. Each chapter has a Google Place ID — pass it to `POST /trips` to create a trip to that chapter's city. **See also:** For a chapter by city or country name (`q='Lisbon'`, `q='Thailand'`), `POST /search/chapters` searches city + country names directly — faster than paginating this member-count-sorted list.

Query parameters

  • limit number default: 50

    Max chapters to return (1-100).

  • cursor string default:

    Cursor from a previous response's `nextCursor`. Pass to fetch the next page.

Response

  • chapters object[]

    Array of chapters, sorted by member count (descending).

    • cityID string

      Chapter ID (same as the Google Place ID)

    • cityName string

      City name

    • country string

      Country

    • countryCode string

      ISO country code

    • placeID string

      Google Place ID — pass to POST /trips to create a trip to this city

    • memberCount number

      Number of members in this chapter

    • upcomingTrips number

      Number of upcoming trips to this chapter

    • chapterURL string

      Link to chapter page on DC (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same chapter.

  • nextCursor string

    Cursor for the next page, or `null` if no more chapters.

Example: List chapters

{
  "data": {
    "chapters": [
      {
        "chapterURL": "https://dc.dynamitecircle.com/chapter/ChIJ82ENKDJgHTERIEjiXbIAAQE",
        "cityID": "ChIJ82ENKDJgHTERIEjiXbIAAQE",
        "cityName": "Bangkok",
        "country": "Thailand",
        "countryCode": "TH",
        "memberCount": 142,
        "placeID": "ChIJ82ENKDJgHTERIEjiXbIAAQE",
        "upcomingTrips": 18
      }
    ]
  },
  "ok": true
}

GET /chapters/:cityID — Get a single chapter

Get full details for a single chapter, including up to 100 home-chapter members and the list of DCers currently visiting via active trips. - `members` — DCers whose **home chapter** is this city (up to 100). - `currentVisitors` — DCers with an active trip to this city (`startDate <= now <= endDate`). Each entry carries a mini `profile` block, the visitor's `tripID`, and trip start/end dates. Use this to answer "who is in <city> right now?" — both locals (via `members`) and visitors (here). Hidden + guest profiles are filtered from both lists.

Path parameters

  • cityID e.g. ChIJ82ENKDJgHTERIEjiXbIAAQE

    Chapter ID (same as Google Place ID)

Response

  • chapter object

    Chapter metadata. Same shape as one entry from `GET /chapters`.

    • cityID string

      Chapter ID (same as the Google Place ID)

    • cityName string

      City name

    • country string

      Country

    • countryCode string

      ISO country code

    • placeID string

      Google Place ID for the chapter city

    • memberCount number

      Number of members whose home chapter is this city

    • upcomingTrips number

      Number of upcoming trips to this chapter

    • chapterURL string

      Link to chapter page on DC (canonical host).

    • shortURL string

      Branded short link (dc.mba) to the same chapter.

  • members object[]

    Up to 100 home-chapter members. Each profile uses the full public-other-person shape (same as `GET /profile-match` results).

  • currentVisitors object[]

    DCers currently in this city via active trips (`startDate <= now <= endDate`). Use this together with `members` to answer "who is in <city> right now?".

    • tripID string

      The visitor's active trip ID.

    • startDate string

      Trip start date (ISO 8601).

    • endDate string

      Trip end date (ISO 8601).

    • profile object

      Mini profile of the visitor.

      • userID string

        User ID.

      • userName string

        Username (handle).

      • displayName string

        Display name.

      • photo string

        Profile photo URL.

      • headline string

        Profile headline.

      • profileURL string

        Profile URL on DC.

Membership

GET /membership — Get your membership state

Returns your full membership state: role, lifecycle dates, trial status, billing/subscription details, and a link to the Stripe Customer Portal where you can manage your subscription, payment methods, and download invoices.

Response

  • membership object

    Full membership state

    • userID string

      Member ID

    • joinedDate string

      Earliest membership start date (ISO 8601).

    • role object

      Role label + machine-readable key

      • label string

        Human-readable role label, e.g. "DC Member", "DC BLACK Member"

      • key string

        Stable key: dcc | black | free | trial | event-guest | inactive | admin | unknown

    • isActive boolean

      Whether the member is currently active

    • isStaff boolean

      Member is on the DC team

    • isAdmin boolean

      Member has admin privileges

    • isExpired boolean

      Membership has expired

    • isCanceled boolean

      Membership has been canceled

    • isInactive boolean

      Member is inactive

    • dcBlack object

      DC BLACK tier membership state

      • isMember boolean

        Currently a DC BLACK member

      • joinedDate string

        When the member joined DC BLACK (ISO)

      • leftDate string

        When the member left DC BLACK (ISO)

    • trial object

      Trial state (if any)

      • isOnTrial boolean

        Currently on a trial

      • wasOnTrial boolean

        Has been on a trial in the past

      • mode string

        Trial mode: manual | stripe | none

      • startDate string

        Trial start (ISO)

      • endDate string

        Trial end (ISO)

      • daysLeft number

        Days remaining in trial

      • duration number

        Total trial duration in days

      • progressPct number

        Trial progress 0–100

    • billing object

      Billing / subscription details

      • status string

        Subscription status: active | trialing | past_due | unpaid | canceled | paused | incomplete | incomplete_expired | no_subscription | free | scheduled | chargify | paypal

      • provider string

        Payment provider: stripe | paypal | chargify | free | none

      • isStripe boolean

        Member is billed via Stripe

      • isPaypal boolean

        Member is on legacy PayPal billing

      • isChargify boolean

        Member is on legacy Chargify billing

      • amount number

        Recurring amount in the smallest currency unit (e.g. cents)

      • amountFormatted string

        Pre-formatted amount, e.g. "$999.00"

      • currency string

        ISO 4217 currency code, e.g. "USD"

      • interval string

        Billing interval base unit, e.g. "month", "year"

      • intervalCount number

        Interval multiplier, e.g. 3 for quarterly

      • frequency string

        Plan frequency: annual | monthly | quarterly | semiannual | biennial | triennial | quinquennial

      • planName string

        Plan name, e.g. "DC Community — Annual"

      • planDescription string

        Plan description

      • currentPeriodStart string

        Current billing period start (ISO)

      • currentPeriodEnd string

        Current billing period end (ISO)

      • currentPeriodNo number

        Which billing period we are on

      • currentPeriodPct number

        Progress through the current period (0–100)

      • nextBillingDate string

        Next renewal/charge date (ISO). Same as currentPeriodEnd in most cases.

      • daysTillRenewal number

        Days until the next charge

      • subscriptionStartDate string

        When the subscription started (ISO)

      • subscriptionEndDate string

        When the subscription ended (ISO, if it has)

      • memberPeriodNo number

        Number of completed renewals

      • hasMultipleSubscriptions boolean

        True if the member has 2+ active subscriptions

      • totalSubscriptions number

        Total active subscription count

    • links object

      Useful URLs

      • manageBillingURL string

        Stripe Customer Portal login URL — manage subscription, payment methods, download invoices. Null for legacy paypal/chargify members.

      • profileURL string

        Public profile URL

Example: Active member with Stripe annual subscription

{
  "data": {
    "membership": {
      "billing": {
        "amount": 99900,
        "amountFormatted": "$999.00",
        "currency": "USD",
        "currentPeriodEnd": "2026-11-15T00:00:00.000Z",
        "currentPeriodNo": 8,
        "currentPeriodPct": 47,
        "currentPeriodStart": "2025-11-15T00:00:00.000Z",
        "daysTillRenewal": 195,
        "frequency": "annual",
        "hasMultipleSubscriptions": false,
        "interval": "year",
        "intervalCount": 1,
        "isChargify": false,
        "isPaypal": false,
        "isStripe": true,
        "memberPeriodNo": 8,
        "nextBillingDate": "2026-11-15T00:00:00.000Z",
        "planDescription": "Yearly DC membership",
        "planName": "DC Community — Annual",
        "provider": "stripe",
        "status": "active",
        "subscriptionEndDate": null,
        "subscriptionStartDate": "2018-04-12T00:00:00.000Z",
        "totalSubscriptions": 1
      },
      "dcBlack": {
        "isMember": false,
        "joinedDate": null,
        "leftDate": null
      },
      "isActive": true,
      "isAdmin": false,
      "isCanceled": false,
      "isExpired": false,
      "isInactive": false,
      "isStaff": false,
      "joinedDate": "2018-04-12T00:00:00.000Z",
      "links": {
        "manageBillingURL": "https://billing.stripe.com/p/login/28o2ayfjS2MTfaE4gg",
        "profileURL": "https://www.dynamitecircle.com/profile/peter"
      },
      "role": {
        "key": "dcc",
        "label": "DC Member"
      },
      "trial": {
        "daysLeft": null,
        "duration": null,
        "endDate": null,
        "isOnTrial": false,
        "mode": "none",
        "progressPct": null,
        "startDate": null,
        "wasOnTrial": true
      },
      "userID": "8wYpQz3KxRm7sNvL2bH9"
    }
  },
  "ok": true
}

GET /membership/invoices — List your Stripe invoices

Returns your Stripe invoices, newest first. Each entry includes a hosted-invoice URL and a PDF link, both safe to share — perfect for self-serve receipts. Returns an empty array for legacy paypal/chargify members or members with no Stripe customer.

Query parameters

  • limit number default: 20

    Max results (1-100)

Response

  • invoices object[]

    Array of Stripe invoices, newest first

    • invoiceID string

      Stripe invoice ID

    • number string

      Human invoice number, e.g. "DC-0042"

    • status string

      Status: draft | open | paid | uncollectible | void

    • amount number

      Total amount in the smallest currency unit (e.g. cents)

    • amountFormatted string

      Pre-formatted amount, e.g. "$999.00"

    • currency string

      ISO 4217 currency code

    • paid boolean

      True if the invoice is fully paid

    • date string

      Invoice creation date (ISO 8601)

    • periodStart string

      Billing period start (ISO 8601)

    • periodEnd string

      Billing period end (ISO 8601)

    • hostedInvoiceURL string

      Hosted invoice page — safe to share, used for online payment + receipt download

    • invoicePDF string

      Direct PDF link to the invoice

    • description string

      Plan / line-item description

Example: List your invoices

{
  "data": {
    "invoices": [
      {
        "amount": 99900,
        "amountFormatted": "$999.00",
        "currency": "USD",
        "date": "2025-11-15T12:00:00.000Z",
        "description": "DC Community — Annual",
        "hostedInvoiceURL": "https://invoice.stripe.com/i/acct_1.../invst_...",
        "invoiceID": "in_1OabCdEFGhijKL",
        "invoicePDF": "https://pay.stripe.com/invoice/.../pdf",
        "number": "DC-0042",
        "paid": true,
        "periodEnd": "2026-11-15T00:00:00.000Z",
        "periodStart": "2025-11-15T00:00:00.000Z",
        "status": "paid"
      }
    ]
  },
  "ok": true
}

Notifications

GET /notifications — Get your notification preferences

Returns your push + email preferences per notification category. Defaults are applied for any preference you have never explicitly set. Email is `null` for `reaction` / `myReaction` because email is not supported for those categories. For the Friday locator email digest, see `GET /locator/settings` — that's a separate concern (outbound digest, not per-event push/email).

Response

  • notifications object

    Notification preferences

    • categories object

      Push + email toggle per category. 12 categories: account, activity, announcement, channel, chat, directMessage, discussion, event, mention, myReaction, photoTag, reaction. `email` is `null` for reaction/myReaction (not supported).

Example: Default notification preferences

{
  "data": {
    "notifications": {
      "categories": {
        "account": {
          "email": true,
          "push": true
        },
        "activity": {
          "email": false,
          "push": true
        },
        "announcement": {
          "email": true,
          "push": true
        },
        "channel": {
          "email": true,
          "push": true
        },
        "chat": {
          "email": true,
          "push": true
        },
        "directMessage": {
          "email": true,
          "push": true
        },
        "discussion": {
          "email": false,
          "push": true
        },
        "event": {
          "email": false,
          "push": true
        },
        "mention": {
          "email": true,
          "push": true
        },
        "myReaction": {
          "email": null,
          "push": true
        },
        "photoTag": {
          "email": false,
          "push": true
        },
        "reaction": {
          "email": null,
          "push": false
        }
      }
    }
  },
  "ok": true
}

PATCH /notifications — Update your notification preferences

Update any subset of your notification preferences. Send only the categories/channels you want to change — the rest stay as-is. Email is rejected for `reaction` / `myReaction` (not supported).

Request body

  • categories object required

    Per-category push/email toggles. Pass only the categories + channels you want to change.

Response

  • updated boolean

    `true` when the patch landed

Example: Disable announcement emails + enable reaction push

{
  "categories": {
    "announcement": {
      "email": false
    },
    "reaction": {
      "push": true
    }
  }
}
{
  "data": {
    "updated": true
  },
  "ok": true
}

Calendar

GET /calendar — Get your iCalendar feed URL + settings

Returns your iCalendar feed URLs and the toggles that control which event categories the feed includes. **Three URLs are returned:** - `httpsURL` — paste into any calendar app that accepts an HTTPS subscription - `webcalURL` — same URL with the `webcal://` scheme; macOS / iOS Calendar opens it directly - `googleURL` — one-click Google Calendar subscribe link The feed includes events you have tickets to, virtual calls, your trips, chapter events, and flagship events — exactly what each `include*` toggle below controls. Tokens are deterministic, so the URLs never change for a given member.

Response

  • calendar object

    Calendar feed URLs + content toggles

    • feed object

      Three subscription URLs for the same feed

      • httpsURL string

        HTTPS URL — works in most calendar apps

      • webcalURL string

        `webcal://` URL — macOS / iOS Calendar opens this directly

      • googleURL string

        Google Calendar one-click subscribe link

    • toggles object

      Booleans controlling what shows up in the feed (all default sensible).

      • includeMyTickets boolean

        Events you have a valid ticket to

      • includeEventAgenda boolean

        Sessions + meetups bookmarked on your event agenda

      • includeVirtualCalls boolean

        Virtual calls (Connect Calls, DC BLACK calls, welcome calls, happy hours)

      • includeMyTrips boolean

        Your posted trips

      • includeFlagshipEvents boolean

        DCBKK + DCMEX flagship events

      • includeDCBlackEvents boolean

        DC BLACK retreats

      • includeHomeChapterEvents boolean

        Events from your home chapter

      • includeFollowedChapterEvents boolean

        Events from chapters you follow

      • includeOtherChapterEvents boolean

        Events from chapters you don't belong to (DCX, global)

Example: Default calendar feed configuration

{
  "data": {
    "calendar": {
      "feed": {
        "googleURL": "https://calendar.google.com/calendar/r?cid=https%3A%2F%2Fdc.dynamitecircle.com%2Fcal%2F8wYpQz3KxRm7sNvL2bH9%2Fa1b2c3d4e5f6g7h8i9j0k1l2.ics",
        "httpsURL": "https://dc.dynamitecircle.com/cal/8wYpQz3KxRm7sNvL2bH9/a1b2c3d4e5f6g7h8i9j0k1l2.ics",
        "webcalURL": "webcal://dc.dynamitecircle.com/cal/8wYpQz3KxRm7sNvL2bH9/a1b2c3d4e5f6g7h8i9j0k1l2.ics"
      },
      "toggles": {
        "includeDCBlackEvents": false,
        "includeEventAgenda": true,
        "includeFlagshipEvents": true,
        "includeFollowedChapterEvents": true,
        "includeHomeChapterEvents": true,
        "includeMyTickets": true,
        "includeMyTrips": false,
        "includeOtherChapterEvents": false,
        "includeVirtualCalls": true
      }
    }
  },
  "ok": true
}

PATCH /calendar — Update calendar feed settings

Update any subset of your calendar feed toggles. Send only the toggles you want to change — omitted fields are left untouched. Returns `{ updated: true }` on success; re-fetch `GET /calendar` if you need the full toggle set + feed URLs (the URLs themselves are stable and don't change when toggles update).

Request body

  • includeDCBlackEvents boolean

    Boolean

  • includeEventAgenda boolean

    Boolean

  • includeFlagshipEvents boolean

    Boolean

  • includeFollowedChapterEvents boolean

    Boolean

  • includeHomeChapterEvents boolean

    Boolean

  • includeMyTickets boolean

    Boolean

  • includeMyTrips boolean

    Boolean

  • includeOtherChapterEvents boolean

    Boolean

  • includeVirtualCalls boolean

    Boolean

Response

  • updated boolean

    `true` when the patch landed

Example: Add DC BLACK retreats + your trips to the feed

{
  "includeDCBlackEvents": true,
  "includeMyTrips": true
}
{
  "data": {
    "updated": true
  },
  "ok": true
}

Limits

GET /limits — Get your effective rate limits + current usage

Returns the effective per-minute and per-day rate limits for your API key, **plus current usage** (how many calls you have already made in the current minute and day windows, when each window resets, and how many calls you have left). Limits derive from your membership tier (DC member: 10/min, 300/day; DC BLACK member and staff: 60/min, 3000/day) unless an admin has set per-key overrides — overrides win when present. The same usage data is also exposed on every API response via the `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `X-RateLimit-Daily-Remaining`, and `X-RateLimit-Daily-Reset` headers. Use this endpoint when you want a JSON snapshot, or the headers when you want to read it on every call.

Response

  • tier string

    Your membership tier (`dcc` or `dcb`). Admins are reported as `dcb`.

    Values: dcc, dcb

  • perMinute number

    Effective per-minute request cap.

  • perDay number

    Effective per-day request cap.

  • tierDefaults object

    The tier defaults — what your limits would be without overrides.

    • perMinute number

      Tier-default per-minute cap

    • perDay number

      Tier-default per-day cap

  • overrides object

    Per-key overrides set by an admin. Each field is the override value (taking precedence over tier default) or `null` when not overridden.

    • perMinute number

      Per-minute override (null = use tier default)

    • perDay number

      Per-day override (null = use tier default)

  • usage object

    Current usage in the active windows. Counts include this very request (the rate-limit middleware increments before this handler runs).

    • minuteUsed number

      Calls already made in the current minute window

    • minuteResetAt string

      When the per-minute window resets (ISO 8601)

    • dailyUsed number

      Calls already made today (UTC day window)

    • dailyResetAt string

      When the per-day window resets (ISO 8601)

    • remaining object

      Calls left before you hit the cap (clamped to 0).

      • perMinute number

        Calls left in the current minute

      • perDay number

        Calls left today

Example: DC BLACK member, no overrides, 3 calls this minute / 127 today

{
  "data": {
    "overrides": {
      "perDay": null,
      "perMinute": null
    },
    "perDay": 3000,
    "perMinute": 60,
    "tier": "dcb",
    "tierDefaults": {
      "perDay": 3000,
      "perMinute": 60
    },
    "usage": {
      "dailyResetAt": "2026-05-01T00:00:00.000Z",
      "dailyUsed": 127,
      "minuteResetAt": "2026-04-30T15:42:00.000Z",
      "minuteUsed": 3,
      "remaining": {
        "perDay": 2873,
        "perMinute": 57
      }
    }
  },
  "ok": true
}

Follows

GET /follows/profiles — List followed DCers

List the DCers you are currently following. Returns the same mini-profile shape used by every other list endpoint, so each entry roundtrips cleanly with `GET /profile/:userID` or `POST /follows/profiles/:userID`. Cap: 150 follows; the response `cap` echoes that so a client can warn the user as they approach the limit. This list also drives the `/locator/digest` `favoritePeople` and `favoriteCities` sections — surface trip + event activity from DCers and cities you care about without scrolling everywhere.

Response

  • profiles object[]

    Mini profiles of every DCer you currently follow.

    • userID string

      DCer userID.

    • displayName string

      Display name (the in-app rendered name).

    • userName string

      URL-safe username / handle.

    • photo string

      Profile photo URL.

  • count number

    How many DCers you currently follow.

  • cap number

    Maximum number of followed DCers.

Example: Two followed DCers

{
  "data": {
    "cap": 150,
    "count": 2,
    "profiles": [
      {
        "displayName": "Dan Andrews",
        "photo": "https://cdn.dynamitecircle.com/profiles/dan.jpg",
        "userID": "27",
        "userName": "DanAndrews"
      },
      {
        "displayName": "Lina Harling",
        "photo": "https://cdn.dynamitecircle.com/profiles/lina.jpg",
        "userID": "2827",
        "userName": "LinaHarling"
      }
    ]
  },
  "ok": true
}

POST /follows/profiles/:userID — Follow a DCer

Follow a DCer. Idempotent — calling it twice with the same userID is safe (no-op the second time). Target must exist and be publicly visible (hidden + guest profiles are refused with 404). You cannot follow yourself. When the cap of 150 is reached, returns `409 follow_limit_reached` with a hint to unfollow someone first. The response includes the new `profile` mini-card and updated `count` so the caller can render the change without re-fetching. This list also drives the `/locator/digest` `favoritePeople` and `favoriteCities` sections — surface trip + event activity from DCers and cities you care about without scrolling everywhere.

Path parameters

  • userID e.g. 940

    userID of the DCer to follow. Discover via `GET /profile-match` or `GET /chapters/:cityID` members lists.

Response

  • profile object

    Mini profile of the just-followed DCer.

    • userID string

      DCer userID.

    • displayName string

      Display name.

    • userName string

      Username / handle.

    • photo string

      Profile photo URL.

  • count number

    How many DCers you follow after this call.

  • cap number

    Maximum number of followed DCers.

DELETE /follows/profiles/:userID — Unfollow a DCer

Unfollow a DCer. Idempotent — unfollowing someone you weren't following is a no-op (still returns 200 with the updated `count`). Use it whenever you want to stop seeing a DCer in your `/locator/digest` favoritePeople section.

Path parameters

  • userID e.g. 940

    userID of the DCer to unfollow.

Response

  • count number

    How many DCers you follow after this call.

  • cap number

    Maximum number of followed DCers.

GET /follows/chapters — List followed chapters

List the DC chapters (city hubs) you are currently following. Each entry is a mini-chapter with the chapter's Google Place ID — useful for creating trips or surfacing activity in that city. Cap: 50 follows. This list also drives the `/locator/digest` `favoritePeople` and `favoriteCities` sections — surface trip + event activity from DCers and cities you care about without scrolling everywhere.

Response

  • chapters object[]

    Mini chapters of every chapter you currently follow.

    • cityID string

      Chapter ID (same as the Google Place ID).

    • city string

      City name (e.g. `Tokyo`).

    • country string

      Country.

    • countryCode string

      ISO 3166-1 alpha-2 country code.

  • count number

    How many chapters you currently follow.

  • cap number

    Maximum number of followed chapters.

Example: One followed chapter

{
  "data": {
    "cap": 50,
    "chapters": [
      {
        "city": "Tokyo",
        "cityID": "ChIJXSModoWLGGARILWiCfeu2M0",
        "country": "Japan",
        "countryCode": "JP"
      }
    ],
    "count": 1
  },
  "ok": true
}

POST /follows/chapters/:cityID — Follow a chapter

Follow a DC chapter (city hub). Idempotent. Target must exist in the chapters list (discover via `GET /chapters`). Cap 50 — hitting it returns `409 follow_limit_reached`. This list also drives the `/locator/digest` `favoritePeople` and `favoriteCities` sections — surface trip + event activity from DCers and cities you care about without scrolling everywhere.

Path parameters

  • cityID e.g. ChIJXSModoWLGGARILWiCfeu2M0

    Chapter ID (Google Place ID). Get from `GET /chapters` (each entry has `cityID`) or `GET /places/search` (`type === "city"`).

Response

  • chapter object

    Mini chapter of the just-followed chapter.

    • cityID string

      Chapter ID.

    • city string

      City name.

    • country string

      Country.

    • countryCode string

      ISO country code.

  • count number

    How many chapters you follow after this call.

  • cap number

    Maximum.

DELETE /follows/chapters/:cityID — Unfollow a chapter

Unfollow a DC chapter. Idempotent — unfollowing a chapter you weren't following is a no-op.

Path parameters

  • cityID e.g. ChIJXSModoWLGGARILWiCfeu2M0

    Chapter ID to unfollow.

Response

  • count number

    How many chapters you follow after this call.

  • cap number

    Maximum.

Discovery

POST /profile-match — Match DCers from a description (or recommend if omitted)

**AI-powered profile matchmaker.** Match DCers against a natural-language description, or — when `query` is omitted — recommend DCers based on your own profile (chapter, industry, expertise, goals). Returns ranked results from a profile-vector search (Gemini embeddings + reranking under the hood). The caller's LLM synthesizes any narrative on top. Stricter rate limits than the standard CRUD endpoints because of the embedding/rerank cost. **Two modes**: - **With `query`**: free-form description ("DCers in Lisbon who run SaaS"). - **Without `query`**: AI builds an implicit query from your profile and returns "DCers you should meet". Useful for cold-start "who should I message this week?" prompts. **Optional structured filters** (combine with either mode, all AND-ed): - `locationChapterPlaceID` — narrow to DCers whose home / base location matches this Google Place ID. Use for "based in X" queries. Resolve via `GET /places/search`. - `locationCurrentPlaceID` — narrow to DCers currently in this place (auto-derived from their last GPS / active trip). Use for "currently in X" / "visiting X" queries. - `eventID` — narrow to DCers holding a valid ticket to this event ("DCers attending DCMEX who run logistics"). Refunded / canceled tickets are excluded. - `isDCB` — when `true`, narrow to DC BLACK members only. - `industry` — exact match on the DCer's primary business industry. - `minTeamSize` — "at least this size" filter on team headcount (only matches DCers whose team-size visibility is shared with all DCers). - `minRevenue` — "at least this revenue" filter on annual revenue (only matches DCers whose revenue visibility is shared with all DCers). - `gender` — exact match on the DCer's self-reported gender. **Note: Gender is sparsely populated — most DCers leave it blank.** Use this as a "narrow if set" hint rather than a hard requirement; combine with `query` for best results.

Request body

  • query string

    Free-form description of the DCers you want to find. Omit to get recommendations based on your own profile.

  • locationChapterPlaceID string

    Optional. Google Place ID — narrows results to DCers based here ("based in X"). Resolve via `GET /places/search`.

  • locationCurrentPlaceID string

    Optional. Google Place ID — narrows results to DCers currently here, whether they live there or are visiting. **Sparsely populated** — `currentLocation` is self-reported and most DCers leave it null, so this filter under-recalls. For "who is in <city> right now?" prefer creating a trip via `POST /trips` and reading `GET /trips/:tripID` — the `discovery.fullPool` block lists locals AND visitors during the trip window. Resolve placeIDs via `GET /places/search`.

  • eventID string

    Optional. DC event ID — narrows results to DCers with a valid ticket (RSVP yes/maybe or paid). Pair with `query` for "DCers attending X who do Y".

  • isDCB boolean

    Optional. When `true`, narrows results to DC BLACK members only.

  • industry string

    Optional. Exact-match filter on the DCer's primary business industry. Allowed values: `SaaS & Tech`, `Marketing Agency`, `Productized Services`, `Ecommerce & Amazon`, `Courses and Info Products`, `Affiliate, Content Creation, or Ad Revenue`, `Professional Services & Industry Specific Consulting`, `Real Estate and Investing`, `Coaching`, `Other`.

  • minTeamSize string

    Optional. "At least this team size" filter — matches DCers whose team-size bucket is >= this value, ordered as `None < 1-2 < 3-5 < 6-9 < 10-14 < 15-19 < 20-34 < 35-49 < 50-74 < 75-99 < 100+`. `Prefer not to say` also exists in the bucket vocabulary but is treated as "unknown" and always filtered out. Only DCers who set their team-size visibility to "all DCers" are matched; the rest are excluded silently.

  • minRevenue string

    Optional. "At least this revenue" filter on annual revenue. Pass any revenue label (e.g. `$1M+`, `$250K+`, `$100K+`); the filter parses to a number and matches DCers at-or-above. Only DCers who set their revenue visibility to "all DCers" are matched; the rest are excluded silently.

  • gender string

    Optional. Exact-match filter on the DCer's self-reported gender. Allowed values: `Man`, `Woman`, `Non-binary`, `Prefer not to say`. **Note: Gender is sparsely populated — most DCers leave it blank** — combine with `query` rather than relying on this alone.

  • noRerank boolean

    Optional. When `true`, skip the keyword reranker and return results in raw vector-similarity order. Useful when the query is fuzzy/semantic (where exact keyword overlap would add noise) or when comparing reranked vs raw ordering.

  • limit number

    Max results (1-50, default 50). Hard cap at 50 — match is expensive; narrow with filters instead of paginating.

Response

  • results object[]

    Ranked profile matches, highest combined score first

    • score number

      Composite ranking score (0-1, higher = better match). When the keyword reranker ran, this is `0.8 * vectorScore + 0.2 * normalizedKeywordScore`. When `noRerank: true` or the query was empty, this equals `vectorScore`. Use this for ordering — it's what the API sorted by.

    • vectorScore number

      Pure vector-similarity score (0-1, higher = closer in embedding space). Derived from the Firestore euclidean distance via `1 / (1 + distance)`. Useful for inspecting raw semantic similarity independent of the keyword overlap.

    • keywordScore number

      Keyword-overlap score from the reranker (uncapped, scale depends on query length). Only present when the reranker ran (i.e. query was a string and `noRerank` was not set). Useful for debugging why a result ranked where it did.

    • profile object

      Standard profile object (same shape used by `/profile`, `/events/:eventID/attendees`, `/chapters/:cityID`, etc.). Sensitive fields (`revenue`, `teamSize`, `connect`) only populate when the owner shared them with all DCers.

Example: Match by description

{
  "limit": 5,
  "query": "DCers in Lisbon who run SaaS"
}
{
  "data": {
    "results": [
      {
        "profile": {
          "chapter": {
            "chapterURL": "https://www.dynamitecircle.com/chapters/lisbon-pt",
            "cityName": "Lisbon",
            "country": "Portugal",
            "countryCode": "PT",
            "placeID": "ChIJ-ZRLfIQzMBQR2bAQQ8sZh90"
          },
          "displayName": "Jane Doe",
          "headline": "Founder, Acme SaaS",
          "industry": "SaaS / Software",
          "joinedDate": "2020-04-12",
          "photo": "https://cdn.dynamitecircle.com/profiles/jane.jpg",
          "profileURL": "https://www.dynamitecircle.com/profile/JaneDoe",
          "userID": "1234",
          "userName": "JaneDoe"
        },
        "score": 0.91
      }
    ]
  },
  "ok": true
}

Example: Recommend (no query — based on your profile)

{
  "limit": 5
}
{
  "data": {
    "results": [
      {
        "profile": {},
        "score": 0.87
      }
    ]
  },
  "ok": true
}

Issues

POST /report-issue — Report an issue or feedback

Submit a bug report, feedback, or question to the DC team. Optionally include a base64-encoded screenshot (PNG, JPEG, or WebP, up to 4 MB raw). **Privacy note:** Screenshots and report text are sent unredacted to the DC team. Don't include passwords, payment details, or other secrets.

Request body

  • text string required

    A short description of the issue or feedback (1–4000 chars).

  • severity string

    Severity: bug | feedback | question. Defaults to "bug".

  • screenshot string

    Optional base64-encoded screenshot. Accepts raw base64 OR a data URL (e.g. `data:image/png;base64,...`). PNG, JPEG, or WebP only. Max 4 MB raw, clamped to 4096×4096; re-encoded server-side to strip EXIF.

  • context object

    Optional structured debug context — anything useful for triage (last error, request payload, endpoint, etc.). Up to 32 keys.

Response

  • data object

    Acknowledgement

    • issueID string

      Server-assigned issue ID

    • submittedAt string

      When the report was received (ISO 8601)

Example: Report a bug

{
  "context": {
    "endpoint": "POST /trips",
    "lastError": "place_lookup_failed"
  },
  "severity": "bug",
  "text": "POST /trips returns 502 when I pass a placeID for Mexico City"
}
{
  "data": {
    "issueID": "fdbk_abc123def456",
    "submittedAt": "2026-05-04T13:45:00.000Z"
  },
  "ok": true
}