Skip to content

Instantly share code, notes, and snippets.

@terrillmoore
Created January 21, 2026 00:48
Show Gist options
  • Select an option

  • Save terrillmoore/dd347f29bf14ba299db588b4cd9ada6c to your computer and use it in GitHub Desktop.

Select an option

Save terrillmoore/dd347f29bf14ba299db588b4cd9ada6c to your computer and use it in GitHub Desktop.
Meetup GraphQL API Reference (February 2025) - Documented from actual testing

Meetup GraphQL API Reference (February 2025)

This document describes the Meetup GraphQL API schema as discovered through testing and introspection in February 2025. The official Meetup API documentation may be incomplete or outdated.

Note: This documents only what we have actually tested. Fields marked "not tested" exist in the schema but have not been verified to work.

Endpoint

POST https://api.meetup.com/gql-ext

Note: The endpoint changed from /gql to /gql-ext sometime before February 2025. The old endpoint returns 404.

Authentication

Include an OAuth2 bearer token in the Authorization header:

Authorization: Bearer <access_token>
Content-Type: application/json

Queries

Get Current User and Memberships

Retrieve the authenticated user's information and their group memberships:

query {
  self {
    id
    name
    memberships {
      edges {
        node {
          id
          name
          urlname
          timezone
        }
        metadata {
          role
        }
      }
    }
  }
}

Response Structure

{
  "data": {
    "self": {
      "id": "user123",
      "name": "User Name",
      "memberships": {
        "edges": [
          {
            "node": {
              "id": "group-id",
              "name": "Group Name",
              "urlname": "group-url-name",
              "timezone": "America/New_York"
            },
            "metadata": {
              "role": "ORGANIZER"
            }
          }
        ]
      }
    }
  }
}

Role Values

The metadata.role field is an enum. Values we have confirmed through testing:

Role Description
ORGANIZER Primary group organizer (tested)
COORGANIZER Co-organizer with event management permissions (tested)
MEMBER Regular group member (tested)

Other role values may exist (e.g., EVENT_ORGANIZER, ASSISTANT_ORGANIZER) but have not been verified.

Get Group Events

Retrieve past events for a group (this is what we have tested):

query GetGroupEvents($urlname: String!, $first: Int!, $after: String) {
  groupByUrlname(urlname: $urlname) {
    id
    name
    urlname
    events(first: $first, after: $after, filter: { status: PAST }) {
      pageInfo {
        endCursor
        hasNextPage
      }
      edges {
        node {
          id
          title
          dateTime
          venues {
            id
            name
            address
            city
            state
            country
          }
        }
      }
    }
  }
}

Additional fields exist but are not tested: description, endTime, eventUrl, going, venues.lat, venues.lng, and others. Use introspection to discover the full schema.

Variables

{
  "urlname": "your-group-urlname",
  "first": 50,
  "after": null
}

Event Filter Status Values

Status Description
PAST Events that have already occurred (tested)

Other status values likely exist (e.g., UPCOMING, CANCELLED, DRAFT) but have not been tested.

Response Structure

{
  "data": {
    "groupByUrlname": {
      "id": "group-id",
      "name": "Group Name",
      "urlname": "group-urlname",
      "events": {
        "pageInfo": {
          "endCursor": "cursor-string",
          "hasNextPage": true
        },
        "edges": [
          {
            "node": {
              "id": "event-id",
              "title": "Event Title",
              "dateTime": "2025-01-15T19:00:00-05:00",
              "venues": [
                {
                  "id": "venue-id",
                  "name": "Venue Name",
                  "address": "123 Main St",
                  "city": "New York",
                  "state": "NY",
                  "country": "US"
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Schema Changes (Historical)

These are breaking changes discovered when migrating from older API versions:

Endpoint Change

Before After
https://api.meetup.com/gql https://api.meetup.com/gql-ext

Membership Query Changes

Before After
memberships(input: {first: N}) memberships (no arguments) - tested
edges.node.isOrganizer: Boolean edges.metadata.role: RoleEnum - tested

Not verified: Whether memberships.totalCount exists (we don't use it).

Event Query Changes

Before After
pastEvents(input: {...}) events(filter: {status: PAST})
event.venue (single object) event.venues (array)

Pagination

The API uses cursor-based pagination following the Relay Connection specification:

  1. Request with first: N to get N items
  2. Check pageInfo.hasNextPage in response
  3. If true, use pageInfo.endCursor as the after parameter in next request
  4. Repeat until hasNextPage is false

Example pagination loop:

all_events = []
cursor = None

while True:
    result = query_events(urlname=group, first=50, after=cursor)
    events = result["groupByUrlname"]["events"]

    for edge in events["edges"]:
        all_events.append(edge["node"])

    if not events["pageInfo"]["hasNextPage"]:
        break

    cursor = events["pageInfo"]["endCursor"]

Event Ordering

Past events are returned in chronological order (oldest first), not reverse chronological. When filtering by date range, iterate through all pages and filter client-side rather than assuming you can stop early.

Error Handling

GraphQL errors are returned with HTTP 200 status but include an errors array:

{
  "errors": [
    {
      "message": "Error description",
      "extensions": {
        "code": "ERROR_CODE"
      }
    }
  ],
  "data": null
}

Common Error Codes

Code Description
RATE_LIMITED Too many requests; includes resetAt timestamp (in code, not tested live)

Other error codes likely exist but have not been encountered in testing.

Introspection

To discover the full schema, use a GraphQL introspection query:

query IntrospectionQuery {
  __schema {
    types {
      name
      fields {
        name
        type {
          name
          kind
          ofType {
            name
            kind
          }
        }
        args {
          name
          type {
            name
            kind
          }
        }
      }
    }
  }
}

Or for a specific type:

query TypeQuery {
  __type(name: "Group") {
    name
    fields {
      name
      type {
        name
        kind
      }
    }
  }
}

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment