Skip to main content

ReadingStatsResponse

Everything the reading dashboard shows, over one window.

devices object[]required
  • Array [
  • booksFinishedinteger<int64>required
    deviceIdstringrequired
    deviceNamestring | nullnullable

    Friendly name where the client sent one, or the API key's label.

    Example: Ash's iPhone
    duration objectrequired

    Reading time split by how it was arrived at.

    Deliberately two numbers rather than one. Time from the compatibility surfaces is reconstructed from the gaps between their writes: it undercounts and cannot see reading done from a downloaded book at all. Presenting a combined figure is fine; hiding that part of it is an estimate is not.

    inferredMsinteger<int64>required

    Milliseconds reconstructed server-side. An underestimate.

    Example: 900000
    measuredMsinteger<int64>required

    Milliseconds reported by a client that measured its own reading.

    Example: 5400000
    totalMsinteger<int64>required

    Convenience sum of the two, so clients do not each reimplement it.

    Example: 6300000
    lastReadAtstring<date-time>required
    pagesReadinteger<int64>required
    sessionsinteger<int64>required
  • ]
  • formats object[]required
  • Array [
  • booksFinishedinteger<int64>required
    duration objectrequired

    Reading time split by how it was arrived at.

    Deliberately two numbers rather than one. Time from the compatibility surfaces is reconstructed from the gaps between their writes: it undercounts and cannot see reading done from a downloaded book at all. Presenting a combined figure is fine; hiding that part of it is an estimate is not.

    inferredMsinteger<int64>required

    Milliseconds reconstructed server-side. An underestimate.

    Example: 900000
    measuredMsinteger<int64>required

    Milliseconds reported by a client that measured its own reading.

    Example: 5400000
    totalMsinteger<int64>required

    Convenience sum of the two, so clients do not each reimplement it.

    Example: 6300000
    formatstringrequired
    Example: cbz
    pagesReadinteger<int64>required
    sessionsinteger<int64>required
  • ]
  • fromstring<date-time>required

    The window actually used, after defaults were applied.

    granularityReadingStatsGranularityrequired

    How finely to bucket the time series.

    Possible values: [day, week, month]

    periods object[]required
  • Array [
  • booksFinishedinteger<int64>required
    Example: 1
    bucketstringrequired

    ISO date of the bucket's start. Weeks start on Monday.

    Example: 2026-06-01
    duration objectrequired

    Reading time split by how it was arrived at.

    Deliberately two numbers rather than one. Time from the compatibility surfaces is reconstructed from the gaps between their writes: it undercounts and cannot see reading done from a downloaded book at all. Presenting a combined figure is fine; hiding that part of it is an estimate is not.

    inferredMsinteger<int64>required

    Milliseconds reconstructed server-side. An underestimate.

    Example: 900000
    measuredMsinteger<int64>required

    Milliseconds reported by a client that measured its own reading.

    Example: 5400000
    totalMsinteger<int64>required

    Convenience sum of the two, so clients do not each reimplement it.

    Example: 6300000
    pagesReadinteger<int64>required
    Example: 120
    sessionsinteger<int64>required
    Example: 4
  • ]
  • series object[]required
  • Array [
  • booksinteger<int64>required

    Distinct books of the series read in the window.

    booksFinishedinteger<int64>required
    duration objectrequired

    Reading time split by how it was arrived at.

    Deliberately two numbers rather than one. Time from the compatibility surfaces is reconstructed from the gaps between their writes: it undercounts and cannot see reading done from a downloaded book at all. Presenting a combined figure is fine; hiding that part of it is an estimate is not.

    inferredMsinteger<int64>required

    Milliseconds reconstructed server-side. An underestimate.

    Example: 900000
    measuredMsinteger<int64>required

    Milliseconds reported by a client that measured its own reading.

    Example: 5400000
    totalMsinteger<int64>required

    Convenience sum of the two, so clients do not each reimplement it.

    Example: 6300000
    pagesReadinteger<int64>required
    seriesIdstring<uuid>required
    seriesNamestringrequired
    Example: Berserk
    sessionsinteger<int64>required
  • ]
  • summary objectrequired

    Headline totals for the window.

    booksinteger<int64>required
    Example: 12
    booksFinishedinteger<int64>required

    Books finished in the window. Unlike time and pages, this is populated for reading that predates session tracking.

    Example: 5
    duration objectrequired

    Reading time split by how it was arrived at.

    Deliberately two numbers rather than one. Time from the compatibility surfaces is reconstructed from the gaps between their writes: it undercounts and cannot see reading done from a downloaded book at all. Presenting a combined figure is fine; hiding that part of it is an estimate is not.

    inferredMsinteger<int64>required

    Milliseconds reconstructed server-side. An underestimate.

    Example: 900000
    measuredMsinteger<int64>required

    Milliseconds reported by a client that measured its own reading.

    Example: 5400000
    totalMsinteger<int64>required

    Convenience sum of the two, so clients do not each reimplement it.

    Example: 6300000
    pagesReadinteger<int64>required
    Example: 1240
    sessionsinteger<int64>required

    Distinct sittings, after adjacent writes were merged.

    Example: 48
    sessionsWithoutDurationinteger<int64>required

    Sittings whose client could report no time at all. A large number here explains a total that looks lower than the reading felt.

    Example: 3
    sessionsWithoutPagesinteger<int64>required

    Sittings whose client reported no page count. Only a reader that measures its own sitting reports one, so this covers reading that predates session tracking as well as apps that only save a position.

    Example: 3
    tostring<date-time>required
    ReadingStatsResponse
    {
    "devices": [
    {
    "booksFinished": 0,
    "deviceId": "string",
    "deviceName": "Ash's iPhone",
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "lastReadAt": "2024-07-29T15:51:28.071Z",
    "pagesRead": 0,
    "sessions": 0
    }
    ],
    "formats": [
    {
    "booksFinished": 0,
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "format": "cbz",
    "pagesRead": 0,
    "sessions": 0
    }
    ],
    "from": "2024-07-29T15:51:28.071Z",
    "granularity": "day",
    "periods": [
    {
    "booksFinished": 1,
    "bucket": "2026-06-01",
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "pagesRead": 120,
    "sessions": 4
    }
    ],
    "series": [
    {
    "books": 0,
    "booksFinished": 0,
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "pagesRead": 0,
    "seriesId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "seriesName": "Berserk",
    "sessions": 0
    }
    ],
    "summary": {
    "books": 12,
    "booksFinished": 5,
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "pagesRead": 1240,
    "sessions": 48,
    "sessionsWithoutDuration": 3,
    "sessionsWithoutPages": 3
    },
    "to": "2024-07-29T15:51:28.071Z"
    }