API V2 Beta Documentation


This update is now live.


New update (will be live promptly).

  • subject.data.meanings and subject.data.readings have a new attribute called accepted_answer where the value is type boolean. Its purpose is to identify what WaniKani evaluates the user’s answer against. User inputs for meanings are evaluated against all meanings where accepted_answer == true. Ditto for readings.


Is this primarily for kanji? Thinking about vocabulary and radicals, are there any cases where a meaning or reading would have accepted_answer == false?

And for kanji, how does this differ from the subject.data.readings[].primary field?


This is for all subjects. But yes, the attribute exists mainly due to some implications in kanji.

With the current content, no. All radical and vocabulary meaning and readings at the moment are accepted_answer == true. There is the possibility for a false case, which you should plan for.

The purpose of primary was to highlight the WaniKani preferred meaning or reading. The implication is that for radicals and vocabulary we evaluate against all meanings and readings (regardless of the primary state). In Kanji, we evaluate against the primary only. Due to this inconsistency we have introduced accepted_answer.

For now we have backfilled all kanji primary == true to have accepted_answer == true. But there could be the case for primary == false && accepted_answer == true

primary — The preferred meaning and reading for the subject
accepted_answer — What WaniKani will evaluate the user answer against


I’ve updated the object model in my docs to include the accepted_answer field.


Would it be possible to get some “POST” endpoints?

Specifically I’m trying to cache a few day’s lessons, and allow a user to answer offline. Optimally, once the user comes back online I’d like to be able to submit to the WaniKani API the following parameters:

  • item they responded to
  • their response (regardless of whether it is correct or not)
  • when they responded (so that A) WaniKani can backdate their response and maintain their SRS progression and B) so that WaniKani can IGNORE the response if the user has answered it more recently or if the item was locked due to SRS review wait-time)

I understand that backdating/blocking a response may not be functionality that is currently scoped for on WaniKani’s services, but I’d be content with the other two parameters alone if possible and I could probably do a lookup myself to block the SRS lockout/more recently answered case.


Not sure if this has been mentioned yet or not (There is a lot of content to read) but I cannnot seem to get the same count as the “Available Next Day” like in the v1 api.

I am getting each summery.Data.Reviews that have an AvailableAt equal to tomorrow’s date. And just summing the SubjectsId.Count.

Am I doing that wrong?

Also another thing:
None of the character’s are pulling in. It’s just funky looking characters.

  "id": 1000,
  "object": "kanji",
  "url": "https://api.wanikani.com/v2/subjects/1000",
  "data_updated_at": "2018-05-21T21:52:02.620694Z",
  "data": {
    "created_at": "2012-10-30T19:49:28.123286Z",
    "level": 17,
    "slug": "å…µ",
    "hidden_at": null,
    "document_url": "https://www.wanikani.com/kanji/%E5%85%B5",
    "characters": "å…µ",
    "meanings": [
        "meaning": "Soldier",
        "primary": true,
        "accepted_answer": true
    "readings": [
        "type": "onyomi",
        "primary": true,
        "reading": "へい",
        "accepted_answer": true
        "type": "onyomi",
        "primary": true,
        "reading": "ひょう",
        "accepted_answer": true
        "type": "kunyomi",
        "primary": false,
        "reading": "None",
        "accepted_answer": false
    "component_subject_ids": [
    "amalgamation_subject_ids": [


Check the character encoding is set to unicode on whatever application you are using to consume/pull the API.

I’ll get back to you on your first question shortly.


I am getting exact numbers between api v1 and api v2 for generating number of reviews for the next day using api v1’s /study_queue and api v2’s /summary

Here is what I am seeing from your accounts v1 /study_queue (redacted personal info):

{"lessons_available": 0,
   "reviews_available": 0,
   "next_review_date": 1527868800,
   "reviews_available_next_hour": 5,
   "reviews_available_next_day": 183}}

And here is your v2 /summary:

{"object": "report",
 "url": "https"//api.wanikani.com/v2/summary",
 "data_updated_at": "2018-06-01T15"03"30.413082Z",
    [{"available_at": "2018-06-01T15:00:00.000000Z", "subject_ids": []}],
    [{"available_at": "2018-06-01T15:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-01T16:00:00.000000Z", "subject_ids": [4181, 4166, 3068, 3193, 8669]},
     {"available_at": "2018-06-01T17:00:00.000000Z", "subject_ids": [3805, 4141, 4229]},
     {"available_at": "2018-06-01T18:00:00.000000Z", "subject_ids": [3782, 3977, 8707, 3801, 7639, 4224, 4241, 4069, 3802, 3761, 3457, 7630, 4092, 3876, 1025, 7701, 3525, 3708, 4363, 3968]},
     {"available_at": "2018-06-01T19:00:00.000000Z", "subject_ids": [3532]},
     {"available_at": "2018-06-01T20:00:00.000000Z", "subject_ids": [4117]},
     {"available_at": "2018-06-01T21:00:00.000000Z", "subject_ids": [3750, 3814, 3539, 7761]},
     {"available_at": "2018-06-01T22:00:00.000000Z", "subject_ids": [3741, 4164, 4078, 3699, 4146, 7480, 4235, 4236, 250, 4237, 4359, 4187, 270, 274, 8788, 271, 273, 383, 4188, 4223, 4211, 4358, 4210, 4234, 4233, 4212, 1029, 4213, 4177, 3390]},
     {"available_at": "2018-06-01T23:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T00:00:00.000000Z", "subject_ids": [1087]},
     {"available_at": "2018-06-02T01:00:00.000000Z", "subject_ids": [1109, 4163, 4287, 4354, 1098]},
     {"available_at": "2018-06-02T02:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T03:00:00.000000Z", "subject_ids": [1120, 1102, 1111, 1095, 1101, 1097, 1106, 1112, 1118, 1099, 1100, 1116, 1090, 1119, 1108, 1094, 1117, 1105, 1113, 1096, 1107, 1103, 1115, 1093, 4365, 4114, 4175, 4189, 4192, 4370, 4303, 8711, 4312, 3629, 4364, 3808, 7762, 4344, 4366, 4158, 4353, 4222, 7485, 4357, 4293, 4356, 4183, 4240, 4264, 4294]},
     {"available_at": "2018-06-02T04:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T05:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T06:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T07:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T08:00:00.000000Z", "subject_ids": []},
     {"available_at": "2018-06-02T09:00:00.000000Z", "subject_ids": [896, 3172, 4067, 4090, 3543, 4112, 4013, 4116, 3218, 3487, 3868, 3690]},
     {"available_at": "2018-06-02T10:00:00.000000Z", "subject_ids": [7491, 4200, 3238, 227, 4065, 7592, 4131]},
     {"available_at": "2018-06-02T11:00:00.000000Z", "subject_ids": [7588, 8781, 4238, 4244, 3244]},
     {"available_at": "2018-06-02T12:00:00.000000Z", "subject_ids": [3236, 889]},
     {"available_at": "2018-06-02T13:00:00.000000Z", "subject_ids": [3166, 3932, 3715, 3515, 3834, 7691, 3884, 3302, 3556, 3223, 3213, 7582, 3168, 223, 890, 873, 894, 759, 754, 742]},
     {"available_at": "2018-06-02T14:00:00.000000Z", "subject_ids": [3851, 8748, 3540, 3820, 916]},
     {"available_at": "2018-06-02T15:00:00.000000Z", "subject_ids": [3108, 3332, 3931, 3956, 3472, 1027, 1019, 255, 3939, 830, 3928, 3104]}]}}

I am going to use Ruby as “psuedo code” to explain what I did. Say the v2 data is assigned to summary:

summary[:data][:reviews].map { |o| o[:subject_ids].count }.sum # Outputs 183

TLDR: Sum the counts of all values of subject_ids in summary.data.reviews.

I think thats the issue? What you want to test against is available_at <= (top of the current hour + 24 hours)


Beautiful! Thank you for the quick response. This is exactly what I needed.

I totally forgot about Encoding and the date was an issue.

By “top of the current hour” do you mean:
Current Time: 12:13 PM EST
Top of cur hour: 1:00 PM EST


Sorry, I used the term too loosely. I meant beginning of the current hour. For your example it’ll be 12:00 PM EST


I understand, thanks again @viet!


Just a heads up.

For /subjects, the payload includes information on the component relationship under component_subject_ids.

We will be replacing it with a new named field, which will be an Array of Objects consisting of the component subject id and position (order of which it should appear). This will make it more explicit on the importance of the ordering.

In addition the payload only outputted distinct results. The distinctness will be removed for the current representation of component relationship and this new upcoming field. So, for example, if a kanji used the same radical twice, then the relationship data will list it twice. This field’s structure will be different than the other *_subject_ids fields.

For a period both the old component field and the new one will be included in the payload to help ease the transition. Eventually the old component field will be dropped.


Any timeline on the API moving from alpha to beta?

(I’m not in a rush or anything, just excited!)


I’m excited too, but not ready for APIv1 to disappear. Still need to finish updating the stats site, and it’s been slow-going.


@rfindley This was written in the original post. I’m partially reminding you of the potential four month delay in case you forgot, but I’m mostly laughing at the optimism in the original post from July of last year that it would only take two months to make the API (sorry @viet :stuck_out_tongue:).


@viet @oldbonsai,

The only API-driven userscript that I’m aware of on the Forums is the Lesson/Review status:

It’s still operating on APIv1 since v1 has an easy datapoint for determining the next available review (even if it’s 4 months away).

The current number of Lessons and Reviews is easy to get from APIv2 via the /summary endpoint.

But I haven’t found a good way to get the Next Review Date without fetching the whole /assignments endpoint. I’m guessing you have that calculated already somewhere since it appears on the Dashboard. Is it exposed anywhere in APIv2?


Believe me we want to. There are a few more changes incoming, which I think you all will appreciate :slight_smile:

Right now it is mainly just tweaking the payload to include all the necessary information in a structure that makes sense. We are dogfooding the API v2 for a certain project, so while we are trying to be proactive in anticipating what the payloads should have, we are at the point of picking on things we have missed and reacting from that.


Sounds like adding “next review date” to the /summary makes the most sense. I’ll add it to my to do.


If y’all ever need help, I’m working for cheap while between contracts. :grin: