Current code
src/polymarket/models/gamma/event.py, line 322
"featured_image": data.get("featuredImage"),
"created_at": data.get("createdAt"),
"updated_at": data.get("updatedAt"),
"published_at": data.get("published_at"), # BUG: should be "publishedAt"
"state": {
Adjacent fields on lines 319–321 all correctly read camelCase keys from the raw API dict ("featuredImage", "createdAt", "updatedAt"). Line 322 alone uses the Python snake_case key "published_at", which will never be present in a raw Gamma API response.
The field declaration at line 272 is:
published_at: datetime | None = Field(default=None, validation_alias="publishedAt")
The validation_alias is only consulted by Pydantic on the direct-parse path (when "state" is already present in the incoming dict — early return at lines 305–306). For every real Gamma API response, _normalize_event runs in mode="before" and constructs a new dict manually; the alias is never consulted on that code path. data.get("published_at") therefore always returns None.
Bug introduced in commit 17f6fdc. None of the four subsequent commits that touched event.py (0138ad6, 60c694a, 4f1fd57) corrected it. It went undetected because the test fixture in test_event_normalizes_groups_from_flat_payload omits publishedAt entirely and makes no assertion on published_at.
Reproduction
from polymarket.models.gamma import Event
raw = {
"id": "123",
"publishedAt": "2026-01-01T00:00:00Z",
"createdAt": "2026-02-01T00:00:00Z",
"updatedAt": "2026-03-01T00:00:00Z",
}
event = Event.parse_response(raw)
assert event.created_at is not None # passes — "createdAt" key is correct
assert event.updated_at is not None # passes — "updatedAt" key is correct
assert event.published_at is None # passes — demonstrates the bug
event.published_at is always None for any event returned from the live Gamma API, regardless of what the server sends.
Impact
Any caller that reads event.published_at (e.g. to sort or filter events by publish date) silently gets None for every live API response. Because the field type is datetime | None, no exception is raised and the data loss goes unnoticed. This affects the raw /events and /events/{id} Gamma endpoints — i.e., essentially all real usage of the Event model.
Suggested fix
One-line fix on line 322:
# before
"published_at": data.get("published_at"),
# after
"published_at": data.get("publishedAt"),
Recommend also adding coverage in test_event_normalizes_groups_from_flat_payload:
# fixture: add publishedAt="2026-01-01T00:00:00Z"
assert event.published_at == datetime(2026, 1, 1, tzinfo=UTC)
That assertion would have caught this at introduction time.
Related
- The same normalizer block is the source of truth for all datetime hydration on the raw-API path; the other three fields in the same block (
featuredImage, createdAt, updatedAt) are correct and serve as the reference pattern.
- Repo is on latest commit
588d664 (2026-05-27) — confirmed not fixed upstream.
Current code
src/polymarket/models/gamma/event.py, line 322Adjacent fields on lines 319–321 all correctly read camelCase keys from the raw API dict (
"featuredImage","createdAt","updatedAt"). Line 322 alone uses the Python snake_case key"published_at", which will never be present in a raw Gamma API response.The field declaration at line 272 is:
The
validation_aliasis only consulted by Pydantic on the direct-parse path (when"state"is already present in the incoming dict — early return at lines 305–306). For every real Gamma API response,_normalize_eventruns inmode="before"and constructs a new dict manually; the alias is never consulted on that code path.data.get("published_at")therefore always returnsNone.Bug introduced in commit
17f6fdc. None of the four subsequent commits that touchedevent.py(0138ad6,60c694a,4f1fd57) corrected it. It went undetected because the test fixture intest_event_normalizes_groups_from_flat_payloadomitspublishedAtentirely and makes no assertion onpublished_at.Reproduction
event.published_atis alwaysNonefor any event returned from the live Gamma API, regardless of what the server sends.Impact
Any caller that reads
event.published_at(e.g. to sort or filter events by publish date) silently getsNonefor every live API response. Because the field type isdatetime | None, no exception is raised and the data loss goes unnoticed. This affects the raw/eventsand/events/{id}Gamma endpoints — i.e., essentially all real usage of theEventmodel.Suggested fix
One-line fix on line 322:
Recommend also adding coverage in
test_event_normalizes_groups_from_flat_payload:That assertion would have caught this at introduction time.
Related
featuredImage,createdAt,updatedAt) are correct and serve as the reference pattern.588d664(2026-05-27) — confirmed not fixed upstream.