Contents Lesson 12 of 17

5 min read · practitioner

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

  1. Here is /calendar/dividends with 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 with filter[symbol]=AAPL.US added, succeeding.
{"errors": {"filter": ["The filter field is required."],
            "filter.date_eq": ["The filter.date eq field is required when filter.symbol is not present."]}}
  1. The second table below is /calendar/splits with no dates at all: read the from and to in 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.
Live API response: apple dividend calendar
Live API response: mda12 splits calendar bare
Live API response: september splits calendar
  1. 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.