list_events_spec (src/polymarket/_internal/actions/gamma.py:369+) accepts closed: bool | None = None and forwards it to _add_optional(params, "closed", closed), which only sets the query parameter when it's not None. So calling client.list_events() sends no closed parameter to the Gamma /events/keyset endpoint — and the Gamma server applies its own default, which is closed=true rather than false.
Live evidence
$ curl -s 'https://gamma-api.polymarket.com/events?series_id=10345&limit=100' \
| jq '[.[] | .closed] | group_by(.) | map({(.[0]|tostring): length}) | add'
{"true": 100}
(Reproduction borrowed from Polymarket/polymarket-cli#71, which reports the same default-mismatch propagating into the CLI. The CLI omits the parameter when neither --closed nor --active is set; py-sdk does the same when callers omit closed.)
Why this looks like a UX gap rather than a deliberate default
ts-sdk's own listEvents docstring examples (packages/client/src/actions/events.ts:144-160) pass closed: false explicitly:
const result = listEvents(client, {
closed: false,
pageSize: 10,
});
So the team already knew omitting closed produces the wrong result for the common "show me current events" workflow. py-sdk's docstrings (async_public.py / public.py) don't document the default behavior at all, and there's no equivalent example that nudges callers to set it. A new user calling client.list_events() to explore the surface surfaces settled-only events without warning.
The public Gamma docs (https://docs.polymarket.com/developers/gamma-markets-api/get-events) say closed defaults to false, which conflicts with the server's actual behavior — so this might also be a server-contract drift rather than purely an SDK gap.
Possible directions
- Document the actual server default — add a docstring note on
closed: bool | None in list_events and list_events_spec clarifying that omitting it returns settled events. Cheapest fix; doesn't change behavior.
- Apply a client-side default
closed=False in list_events and the equivalent secure-client method so the SDK behavior matches the Gamma docs and ts-sdk's example usage. Behavior-changing, but matches the "intent" already encoded in ts-sdk. Same question would apply to list_markets if it has the same pattern.
- Server-side: change the Gamma default to
false so docs + server + SDK all agree. Out of scope for this repo but worth flagging back to the API team.
I'd lean (2) — ts-sdk's examples already codify closed: false as the right default, so making py-sdk match is consistent and removes a footgun. But this is a contract decision that could go differently.
Cross-SDK / cross-repo
Same pattern in ts-sdk: Polymarket/ts-sdk#75 (ListEventsRequestSchema.closed = z.boolean().optional() + toEventsSearchParams drops undefined). Same root cause in Polymarket/polymarket-cli#71 (the original CLI-side report).
Happy to PR (1) or (2) once you've decided which direction is right.
list_events_spec(src/polymarket/_internal/actions/gamma.py:369+) acceptsclosed: bool | None = Noneand forwards it to_add_optional(params, "closed", closed), which only sets the query parameter when it's notNone. So callingclient.list_events()sends noclosedparameter to the Gamma/events/keysetendpoint — and the Gamma server applies its own default, which isclosed=truerather thanfalse.Live evidence
(Reproduction borrowed from Polymarket/polymarket-cli#71, which reports the same default-mismatch propagating into the CLI. The CLI omits the parameter when neither
--closednor--activeis set; py-sdk does the same when callers omitclosed.)Why this looks like a UX gap rather than a deliberate default
ts-sdk's own
listEventsdocstring examples (packages/client/src/actions/events.ts:144-160) passclosed: falseexplicitly:So the team already knew omitting
closedproduces the wrong result for the common "show me current events" workflow. py-sdk's docstrings (async_public.py/public.py) don't document the default behavior at all, and there's no equivalent example that nudges callers to set it. A new user callingclient.list_events()to explore the surface surfaces settled-only events without warning.The public Gamma docs (https://docs.polymarket.com/developers/gamma-markets-api/get-events) say
closeddefaults tofalse, which conflicts with the server's actual behavior — so this might also be a server-contract drift rather than purely an SDK gap.Possible directions
closed: bool | Noneinlist_eventsandlist_events_specclarifying that omitting it returns settled events. Cheapest fix; doesn't change behavior.closed=Falseinlist_eventsand the equivalent secure-client method so the SDK behavior matches the Gamma docs and ts-sdk's example usage. Behavior-changing, but matches the "intent" already encoded in ts-sdk. Same question would apply tolist_marketsif it has the same pattern.falseso docs + server + SDK all agree. Out of scope for this repo but worth flagging back to the API team.I'd lean (2) — ts-sdk's examples already codify
closed: falseas the right default, so making py-sdk match is consistent and removes a footgun. But this is a contract decision that could go differently.Cross-SDK / cross-repo
Same pattern in ts-sdk: Polymarket/ts-sdk#75 (
ListEventsRequestSchema.closed = z.boolean().optional()+toEventsSearchParamsdropsundefined). Same root cause in Polymarket/polymarket-cli#71 (the original CLI-side report).Happy to PR (1) or (2) once you've decided which direction is right.