API V2 Beta Documentation

Thank you!

Iā€™m playing around with the API V2 but I got stuck and I wonder if someone has a suggestion.

The following command succeeds from bash:

curl "https://api.wanikani.com/v2/study_materials?level=1" \
  -H "Wanikani-Revision: 20170710" \
  -H "Authorization: Bearer <MY_API_V2_ID>"

I then try to load it in a google sheet in tabular form.
I set A1 to =IMPORTJSON(ā€œhttps://api.wanikani.com/v2/study_materials?level=1ā€ -H ā€œWanikani-Revision: 20170710ā€ -H ā€œAuthorization: Bearer <MY_API_V2_ID>ā€)
but I get an ā€œError Formula parse error.ā€

I used to do something similar with the API V1 and a google sheet a couple of years ago, but memory doesnā€™t serve me right :confused:

Does any of you have some suggestions please?

On your spreadsheet, go to [Tools->Script Editor]

Add the following function to the code window (and save):

function WanikaniApi(url) {
  var params = {
    headers: {
      "Authorization": "Bearer <your_apiv2_key>",
      "Wanikani-Revision": "20170710"
    }
  };
  
  return UrlFetchApp.fetch(url, params).getContentText();
}

Then add this to your cell:

=WanikaniAPI("https://api.wanikani.com/v2/study_materials?levels=1")
1 Like

Want to point out to use levels instead of level :slight_smile:

2 Likes

Thanks! Iā€™ve updated it.

Is it also supposed to have levels[]=1 ?
I havenā€™t used the parameters (I think)ā€¦

1 Like

The API used to take in param arrays, but we converted over to delimited comma a while back based on feedback.

For singular level request levels=1 and for multiple levels=1,2,3.

2 Likes

I hadnā€™t played with Google Spreadsheetsā€™ scripting ability much, so this is interesting (and itā€™s how I learn!).
I took a moment to put together a usesful demo, rather than just putting raw API JSON in a cell:

var apiv2_key = 'your_apiv2_key';
var base_url = 'https://api.wanikani.com/v2/';

function WkApi(endpoint) {
  var params = {
    headers: {
      'Authorization': 'Bearer ' + apiv2_key,
      'Wanikani-Revision': "20170710"
    }
  };

  // Return the raw json object.
  return JSON.parse(UrlFetchApp.fetch(base_url + endpoint, params).getContentText());
}

function WkSubjects(level) {
  var json = WkApi('/subjects?levels='+level);

  // Turn the JSON content into a 2D array:
  // [[level, slug], [level, slug], ... ]
  return json.data.map(function(item){
    return [item.data.level, item.data.slug];
  });
}

and formula:

=WkSubjects("1,2")

Result:
image

2 Likes

Ohhhh, that looks handy. Iā€™m not much of a programmer but I can DO some spreadsheet data nerdery.

Thank you @rfindley and @viet . Iā€™m going to try your suggestions this weekend !

Iā€™ve just had time to play with this and everything is working well. Thank you.

1 Like

Iā€™ve been playing some more with Google sheets and the API V2, but I got stuck again.

Iā€™ve got the WkSubjects function working well (thanks to @rfindley and @viet). When I set the A2 cell to =WkSubjects(ā€œ2ā€), I get all radicals, kanji and vocabulary for lesson 2.

var apiv2_key = '<MY_API_V2_KEY>';
var base_url = 'https://api.wanikani.com/v2/';

function WkApi(endpoint) {
  var params = {
    headers: {
      'Authorization': 'Bearer ' + apiv2_key,
      'Wanikani-Revision': "20170710"
    }
  };

  return JSON.parse(UrlFetchApp.fetch(base_url + endpoint, params).getContentText());
}

function WkSubjects(level) {
  var json = WkApi('/subjects?levels='+level);

  return json.data.map(function(item){
    return [item.data.level
          , item.data.characters
          , item.data.meanings[0].meaning
          , item.data.meaning_mnemonic
          , item.data.meaning_hint
          , item.data.reading_mnemonic
          , item.data.reading_hint];
  });
}

You see that I have used ā€œitem.data.meanings[0].meaningā€ that retrieve the value of the ā€œmeaningā€ attribute of the first object in the ā€œmeaningsā€ array of objects.

I would like to return the value of the ā€œmeaningā€ attribute for all the objects in the ā€œmeaningsā€ array of objects and concatenate them with a comma.

This is the function I came out with. I know itā€™s wrong, but js is not my strong suit and an hour on google didnā€™t help.

function WkSubjectsType(level,subject_type) {
  var json = WkApi('/subjects?levels='+level+'&subject_types='+subject_type);

  return json.data.map(function(item){
    var joined = item.data.meanings[(meanings).join(',')];

    
    return [item.data.level
          , item.data.characters
          , joined];
  });
}

Not sure if I should use a foreach loop or perhaps there is a quicker way to do it. Do you have any suggestions for me?

For example


var apiv2_key = '';
var base_url = 'https://api.wanikani.com/v2/';

function WkApi(endpoint) {
  var params = {
    headers: {
      'Authorization': 'Bearer ' + apiv2_key,
      'Wanikani-Revision': "20170710"
    }
  };

  // Return the raw json object.
  return JSON.parse(UrlFetchApp.fetch(base_url + endpoint, params).getContentText());
}

function WkSubjects(level) {
  var json = WkApi('/subjects?levels='+level);
  return json.data.map(function(item){
    return [item.data.level, item.data.slug, FormatMeanings(item.data)];
  });
}

function FormatMeanings(data) {
  return data.meanings.map(function(meaning){
    return meaning.meaning;
  }).join(', ');
}
1 Like

Thank you @Tombow ! I see what you did there.
Iā€™ve just tried this out and it works well.

1 Like

Iā€™ve stumbled across a problem I cannot solve.

If I use a command like:

curl "https://api.wanikani.com/v2/study_materials?subject_types=kanji" \
  -H "Wanikani-Revision: 20170710" \
  -H "Authorization: Bearer <my_api_v2>" \
  | python -m json.tool \
  > study_materials-kanji.txt

I get meaning_note, meaning_synonyms,reading_note
but I donā€™t get level, meanings, meaning_hint, meaning_mnemonic, readings, reading_hint, reading_mnemonic.

If I use a command like:

curl "https://api.wanikani.com/v2/subjects?level=1&types=kanji" \
  -H "Wanikani-Revision: 20170710" \
  -H "Authorization: Bearer <my_api_v2>" \
  | python -m json.tool \
  > subjects-types_kanji-level_1.txt

I get level, meanings, meaning_hint, meaning_mnemonic, readings, reading_hint, reading_mnemonic
but I donā€™t get meaning_note, meaning_synonyms,reading_note

How do I make a ā€œunionā€ of these two data sets?

Is there a command to get all these attributes in one go:
level
characters
meanings
meaning_hint
meaning_mnemonic
meaning_synonyms
meaning_note
readings
reading_hint
reading_mnemonic
reading_note

Or do I have to get the two data sets individually and then ā€œjoinā€ them with js (which I wouldnā€™t know how to do)?

Or do I have to do something completely different?

They are disjoint and youā€™ll have to merge them yourself. The subjects are the radicals, kanji and vocab, the shared data as created and offered by WK. The study materials are your own notes and synonyms that you added for yourself. Subjects are shared, study materials are private.

1 Like

Thank you @ejplugge . I hadnā€™t notice that difference between subjects and study materials.

I understand that this conceptual difference is necessary for a wanikani administrator who can see a 1:many relationship between subjects and study materials.

For a wanikani user however, who can only see his/her own study materials, it may create an unnecessary complication. I wonder whether the creation of a unified set that comprises both subjects and study materials may be an improvement to a typical wanikani userā€™s utilisation of the API.

Do you know of a guide or documentation where I could learn the steps to join these two sets? I wouldnā€™t quite know where to start.

Itā€™s a pretty standard way of setting up an API for software developers, which is who the API is intended for.

But anyway, the link between the two is the subject_id field. Do your initial search in whichever table makes the most sense for whatever youā€™re searching for, then extract the subject_id field from those records, and look up the additional information by subject_id in the other table(s).

2 Likes

From an API design standpoint, the split chosen by the devs is the cleaner, more correct one. For example, this approach will work much more nicely with caching. I fear this is just something youā€™ll have to deal with :frowning:

I donā€™t know of a ready-to-use tool you can use, although they may exist. But for this kind of thing, it generally boils down to just having to write the code yourself, reading both files, going through the study materials one by one and adding them to the subjects based on the ā€œidā€ field in the subject and the ā€œsubject_idā€ field in the study materials. You can use whatever standard data manipulation features of whatever language you want to use (JavaScript, Python, Ruby, ā€¦) and the documentation that comes with those scripting languages. Or if you want to use a spreadsheet, loading the two data sets into different tabs and combining them with a couple of smart formulas/pivots should also work.

But youā€™ll have to know how to use those languages/tools, otherwise youā€™ll get stuck quickly, Iā€™m afraid.

1 Like

Thank you @ejplugge

At present Iā€™m ok with reading the /subjects or /table but I have troubles with caching it into a database table in the browser. Incidentally @rfindley has just mentioned to me the Open Framework (that I didnā€™t know). It seems to contain what Iā€™m missing, so Iā€™ll start going through its documentation.

Is there any way to find out when a user did the lesson for a specific item? I know that you can find the unlock date with API V1, and the first review with API V2, but I can find a way to tell when the lesson was actually done.