Skip to main content

ReadingStatsResponse

Everything the reading dashboard shows, over one window.

devices object[]required
  • Array [
  • 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 [
  • 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.

    granularityReadingStatsGranularity (string)required

    How finely to bucket the time series.

    Possible values: [day, week, month]

    periods object[]required
  • Array [
  • 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.

    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
    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
    tostring<date-time>required
    ReadingStatsResponse
    {
    "devices": [
    {
    "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": [
    {
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "format": "cbz",
    "pagesRead": 0,
    "sessions": 0
    }
    ],
    "from": "2024-07-29T15:51:28.071Z",
    "granularity": "day",
    "periods": [
    {
    "bucket": "2026-06-01",
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "pagesRead": 120,
    "sessions": 4
    }
    ],
    "series": [
    {
    "books": 0,
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "pagesRead": 0,
    "seriesId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "seriesName": "Berserk",
    "sessions": 0
    }
    ],
    "summary": {
    "books": 12,
    "duration": {
    "inferredMs": 900000,
    "measuredMs": 5400000,
    "totalMs": 6300000
    },
    "pagesRead": 1240,
    "sessions": 48,
    "sessionsWithoutDuration": 3
    },
    "to": "2024-07-29T15:51:28.071Z"
    }