Status
Confirmed on 2026-09-13 against the live GET /v1/subscriptions/events body and oilpriceapi-api origin/main app/models/watch_event.rb#as_poll_json. The SDK code is origin/main a5304b3, oilpriceapi/models.py SubscriptionEvent.
Defect
SubscriptionEvent models fields the API does not send, and leaves the fields it does send untyped.
| SDK field |
On the wire? |
seq |
yes |
watch_id |
yes |
type |
no |
code |
no |
payload |
no |
created_at |
no: the timestamp is observed_at |
Wire fields the model does not declare, reachable only as untyped pydantic extras (extra="allow"): id, observed_at (ISO string, not parsed to datetime), snapshot, deltas, source, tool_name.
Consequences:
- The docstring example on
origin/main, print(event.type, event.code), prints None None for every real event.
event.created_at is always None.
- Price data (
snapshot, deltas) has no type.
Repro
Live body, GET /v1/subscriptions/events?since=99&limit=2, one event shown:
{"id": "d73c7b25-875b-403e-a429-0d7049245c30", "seq": 100,
"watch_id": "b84b24a0-2b28-4eac-835e-db92bab5c0cb",
"observed_at": "2026-09-08T16:20:42Z",
"snapshot": {"BRENT_CRUDE_USD": {"as_of": "2026-09-08T16:16:14Z", "price": 97.27, "currency": "USD", "change_24h_pct": -0.04}},
"deltas": {"BRENT_CRUDE_USD": {"pct_change": -0.53, "price_change": -0.52}},
"source": "api", "tool_name": "opa_create_price_subscription"}
from oilpriceapi.models import SubscriptionEvent
e = SubscriptionEvent(**event)
print(e.type, e.code, e.created_at) # None None None
print(type(e.observed_at)) # <class 'str'> (an extra, not a datetime)
Expected
Type id, observed_at (a datetime), snapshot, deltas, source and tool_name from the wire shape. Either keep type/code/payload/created_at as deprecated aliases or drop them in a minor release with a CHANGELOG note. Apply to sync and async; they share the model.
PR #147 (#142) already changes the events() docstring example to event.seq, event.watch_id. It does not change the model.
Status
Confirmed on 2026-09-13 against the live
GET /v1/subscriptions/eventsbody and oilpriceapi-apiorigin/mainapp/models/watch_event.rb#as_poll_json. The SDK code isorigin/maina5304b3,oilpriceapi/models.pySubscriptionEvent.Defect
SubscriptionEventmodels fields the API does not send, and leaves the fields it does send untyped.seqwatch_idtypecodepayloadcreated_atobserved_atWire fields the model does not declare, reachable only as untyped pydantic extras (
extra="allow"):id,observed_at(ISO string, not parsed todatetime),snapshot,deltas,source,tool_name.Consequences:
origin/main,print(event.type, event.code), printsNone Nonefor every real event.event.created_atis alwaysNone.snapshot,deltas) has no type.Repro
Live body,
GET /v1/subscriptions/events?since=99&limit=2, one event shown:{"id": "d73c7b25-875b-403e-a429-0d7049245c30", "seq": 100, "watch_id": "b84b24a0-2b28-4eac-835e-db92bab5c0cb", "observed_at": "2026-09-08T16:20:42Z", "snapshot": {"BRENT_CRUDE_USD": {"as_of": "2026-09-08T16:16:14Z", "price": 97.27, "currency": "USD", "change_24h_pct": -0.04}}, "deltas": {"BRENT_CRUDE_USD": {"pct_change": -0.53, "price_change": -0.52}}, "source": "api", "tool_name": "opa_create_price_subscription"}Expected
Type
id,observed_at(adatetime),snapshot,deltas,sourceandtool_namefrom the wire shape. Either keeptype/code/payload/created_atas deprecated aliases or drop them in a minor release with a CHANGELOG note. Apply to sync and async; they share the model.PR #147 (#142) already changes the
events()docstring example toevent.seq, event.watch_id. It does not change the model.