Why do the split and dividend calendars look nothing alike?
/calendar/splits and /calendar/dividends answer the same shape of question — what is scheduled, between these dates — and they have almost nothing in common as interfaces. This is not a quirk to memorise and forget. It is the single most useful worked example of why you read the spec for each endpoint rather than pattern-matching from the last one.
The splits calendar: the older convention
GET /calendar/splits?from=2018-12-02&to=2018-12-06&fmt=json
Flat query parameters. from defaults to today, to to seven days out, fmt defaults to csv. The response wraps a splits array in an envelope carrying type, description, from and to.
Each record:
code: "AINV.US" split_date: "2018-12-03"
optionable: "N" old_shares: 3 new_shares: 1
Note optionable, which is "Y" or "N" — a string flag, not a boolean. And note the field pair old_shares/new_shares, which as the earlier splits lesson showed is the mirror of the "new/old" string that /splits/{ticker} returns. Here old_shares: 3, new_shares: 1 is a 1-for-3 reverse split: 300 shares become 100.
The dividends calendar: the JSON:API convention
GET /calendar/dividends?filter[symbol]=AAPL.US&page[limit]=100
Bracketed, namespaced parameters. filter[date_eq], filter[date_from], filter[date_to], filter[symbol], page[limit] (1–10000), page[offset] (0–1,000,000). fmt defaults to json here, the opposite of its sibling. The response is { meta, data, links } — pagination metadata, the array, and JSON:API pagination links.
And the behaviour that will catch you first: at least one of filter[date_eq] or filter[symbol] is required. A bare call returns HTTP 422, with a body like:
errors: {
filter: ["The filter field is required."],
filter.date_eq: ["The filter.date eq field is required
when filter.symbol is not present."]
}
That is a well-designed refusal — the endpoint is declining to scan every dividend on earth — but it is a 422, not a 400, and it arrives with a structured error object rather than a plain message. Handle it specifically.
Six differences in one table
/calendar/splits |
/calendar/dividends |
|
|---|---|---|
| Date params | from / to |
filter[date_eq] / filter[date_from] / filter[date_to] |
| Symbol filter | none | filter[symbol] |
| Pagination | none | page[limit], page[offset] |
fmt default |
csv |
json |
| Empty call | returns a week | returns 422 |
| Envelope | type/description/from/to + array |
meta/data/links |
Why this happens, and what to do about it
Any API of real size grows in layers. Older endpoints carry the conventions of the year they were written; newer ones carry today's. A provider can either keep the old shapes working or break every client that depends on them. Most choose stability, and the visible cost is exactly the inconsistency above.
The practical response is not irritation, it is a thin adapter per endpoint. Write one function per path that takes your own uniform arguments — a symbol, a date range, a page — and translates them into whatever that specific endpoint wants. Then the inconsistency lives in one file rather than being smeared through your application, and the next convention change is a small edit.
This is also the reason to read the parameter list every time. Two endpoints in the same family, released years apart, is all it takes.
Try it now
- Here is
/calendar/dividendswith no parameters, called on 28 September 2026: status 422, and this body. Read both messages and say which parameter would satisfy each. The first table below is the same call withfilter[symbol]=AAPL.USadded, succeeding.
{"errors": {"filter": ["The filter field is required."],
"filter.date_eq": ["The filter.date eq field is required when filter.symbol is not present."]}}
- The second table below is
/calendar/splitswith no dates at all: read thefromandtoin its envelope and count the days between them. It happily returns a week. The last table is the same endpoint over a window you choose. Two endpoints, two philosophies about what a bare request means.
- Write one adapter function with the signature
upcoming(kind, symbol, start, end, page)that dispatches to both. The body of that function is this lesson.