Anki REST API
Anki-API's capabilities include executing queries against the user's card deck, automatically creating new cards, and more.
Anki-Connect is compatible with the latest stable (2.1.x) releases of Anki; older versions (2.0.x and below) are no longer supported.
β οΈ Warning: This a fork in development. Expect bugs.
Notes for Windows Users
Windows users may see a firewall nag dialog box appear on Anki startup. This occurs because Anki-Connect runs a local
HTTP server in order to enable other applications to connect to it. The host application, Anki, must be unblocked for
this plugin to function correctly.
Notes for MacOS Users
Starting with Mac OS X Mavericks, a feature named App Nap has been
introduced to the operating system. This feature causes certain applications which are open (but not visible) to be
placed in a suspended state. As this behavior causes Anki-Connect to stop working while you have another window in the
foreground, App Nap should be disabled for Anki:
- Start the Terminal application.
- Execute the following commands in the terminal window:
defaults write net.ankiweb.dtop NSAppSleepDisabled -bool true
defaults write net.ichi2.anki NSAppSleepDisabled -bool true
defaults write org.qt-project.Qt.QtWebEngineCore NSAppSleepDisabled -bool true
- Restart Anki.
Application Interface for Developers
Anki-Connect exposes internal Anki features to external applications via an easy to use API. After being installed, this
plugin will start an HTTP server on port 8765 whenever Anki is launched. Other applications (including browser
extensions) can then communicate with it via HTTP requests.
By default, Anki-Connect will only bind the HTTP server to the 127.0.0.1 IP address, so that you will only be able to
access it from the same host on which it is running. If you need to access it over a network, you can change the
binding address in the configuration. Go to Tools->Add-ons->AnkiConnect->Config and change the "webBindAddress"
value. For example, you can set it to 0.0.0.0 in order to bind it to all network interfaces on your host. This also
requires a restart for Anki.
Sample Invocation
Every request consists of a JSON-encoded object containing an action, a version, contextual params, and a key
value used for authentication (which is optional and can be omitted by default). Anki-Connect will respond with an
object containing two fields: result and error. The result field contains the return value of the executed API,
and the error field is a description of any exception thrown during API execution (the value null is used if
execution completed successfully).
Sample successful response:
{"result": ["Default", "Filtered Deck 1"], "error": null}
Samples of failed responses:
{"result": null, "error": "unsupported action"}
{"result": null, "error": "guiBrowse() got an unexpected keyword argument 'foobar'"}
For compatibility with clients designed to work with older versions of Anki-Connect, failing to provide a version
field in the request will make the version default to 4. Furthermore, when the provided version is level 4 or below, the
API response will only contain the value of the result; no error field is available for error handling.
You can use whatever language or tool you like to issue request to Anki-Connect, but a couple of simple examples are
included below as reference.
Curl
curl localhost:8765 -X POST -d '{"action": "deckNames", "version": 6}'
Powershell
(Invoke-RestMethod -Uri http://localhost:8765 -Method Post -Body '{"action": "deckNames", "version": 6}').result
Python
import json
import urllib.request
def request(action, **params):
return {'action': action, 'params': params, 'version': 6}
def invoke(action, **params):
requestJson = json.dumps(request(action, **params)).encode('utf-8')
response = json.load(urllib.request.urlopen(urllib.request.Request('http://localhost:8765', requestJson)))
if len(response) != 2:
raise Exception('response has an unexpected number of fields')
if 'error' not in response:
raise Exception('response is missing required error field')
if 'result' not in response:
raise Exception('response is missing required result field')
if response['error'] is not None:
raise Exception(response['error'])
return response['result']
invoke('createDeck', deck='test1')
result = invoke('deckNames')
print('got list of decks: {}'.format(result))
JavaScript
function invoke(action, version, params={}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.addEventListener('error', () => reject('failed to issue request'));
xhr.addEventListener('load', () => {
try {
const response = JSON.parse(xhr.responseText);
if (Object.getOwnPropertyNames(response).length != 2) {
throw 'response has an unexpected number of fields';
}
if (!response.hasOwnProperty('error')) {
throw 'response is missing required error field';
}
if (!response.hasOwnProperty('result')) {
throw 'response is missing required result field';
}
if (response.error) {
throw response.error;
}
resolve(response.result);
} catch (e) {
reject(e);
}
});
xhr.open('POST', 'http://127.0.0.1:8765');
xhr.send(JSON.stringify({action, version, params}));
});
}
await invoke('createDeck', 6, {deck: 'test1'});
const result = await invoke('deckNames', 6);
console.log(`got list of decks: ${result}`);
Hey, could you add a new action to support $FEATURE?
The primary goal for Anki-Connect was to support real-time flash card creation from the
Yomichan browser extension. The current API provides all the required actions
to make this happen. I recognise that the role of Anki-Connect has evolved from this original vision, and I am happy to
review new feature requests.
With that said, this project operates on a self-serve model. If you would like a new feature, create a PR. I'll review
it and if it looks good, it will be merged in. Requests to add new features without accompanying pull requests will not
be serviced. Make sure that your pull request meets the following criteria:
- Attempt to match style of the surrounding code.
- Have accompanying documentation with examples.
- Have accompanying tests that verify operation.
- Implement features useful in other applications.
Supported Actions
Documentation for currently supported actions is split up by category and is referenced below. Note that deprecated APIs
will continue to function despite not being listed on this page as long as your request is labeled with a version number
corresponding to when the API was available for use.
Card Actions
getEaseFactors
setEaseFactors
setSpecificValueOfCard
-
Sets specific value of a single card. Given the risk of wreaking havor in the database when changing some of the values of a card, some of the keys require the argument "warning_check" set to True.
This can be used to set a card's flag, change it's ease factor, change the review order in a filtered deck and change the column "data" (not currently used by anki apparantly), and many other values.
A list of values and explanation of their respective utility can be found at AnkiDroid's wiki.
Sample request:
{
"action": "setSpecificValueOfCard",
"version": 6,
"params": {
"card": 1483959291685,
"keys": ["flags", "odue"],
"newValues": ["1", "-100"]
}
}
Sample result:
{
"result": [true, true],
"error": null
}
suspend
unsuspend
suspended
areSuspended
areDue
getIntervals
findCards
cardsToNotes
cardsModTime
cardsInfo
-
Returns a list of objects containing for each card ID the card fields, front and back sides including CSS, note
type, the note that the card belongs to, and deck name, last modification timestamp as well as ease and interval.
Sample request:
{
"action": "cardsInfo",
"version": 6,
"params": {
"cards": [1498938915662, 1502098034048]
}
}
Sample result:
{
"result": [
{
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 1,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"css":"p {font-family:Arial;}",
"cardId": 1498938915662,
"interval": 16,
"note":1502298033753,
"ord": 1,
"type": 0,
"queue": 0,
"due": 1,
"reps": 1,
"lapses": 0,
"left": 6,
"mod": 1629454092
},
{
"answer": "back content",
"question": "front content",
"deckName": "Default",
"modelName": "Basic",
"fieldOrder": 0,
"fields": {
"Front": {"value": "front content", "order": 0},
"Back": {"value": "back content", "order": 1}
},
"css":"p {font-family:Arial;}",
"cardId": 1502098034048,
"interval": 23,
"note":1502298033753,
"ord": 1,
"type": 0,
"queue": 0,
"due": 1,
"reps": 1,
"lapses": 0,
"left": 6
}
],
"error": null
}
forgetCards
relearnCards
Deck Actions
deckNames
deckNamesAndIds
getDecks
createDeck
changeDeck
deleteDecks
getDeckConfig
saveDeckConfig
setDeckConfigId
cloneDeckConfigId
-
Creates a new configuration group with the given name, cloning from the group with the given ID, or from the default
group if this is unspecified. Returns the ID of the new configuration group, or false if the specified group to
clone from does not exist.
Sample request:
{
"action": "cloneDeckConfigId",
"version": 6,
"params": {
"name": "Copy of Default",
"cloneFrom": 1
}
}
Sample result:
{
"result": 1502972374573,
"error": null
}
removeDeckConfigId
-
Removes the configuration group with the given ID, returning true if successful, or false if attempting to
remove either the default configuration group (ID = 1) or a configuration group that does not exist.
Sample request:
{
"action": "removeDeckConfigId",
"version": 6,
"params": {
"configId": 1502972374573
}
}
Sample result:
{
"result": true,
"error": null
}
getDeckStats
Graphical Actions
guiBrowse
guiSelectedNotes
guiAddCards
-
Invokes the Add Cards dialog, presets the note using the given deck and model, with the provided field values and tags.
Invoking it multiple times closes the old window and reopen the window with the new provided values.
Audio, video, and picture files can be embedded into the fields via the audio, video, and picture keys, respectively.
Refer to the documentation of addNote and storeMediaFile for an explanation of these fields.
The result is the ID of the note which would be added, if the user chose to confirm the Add Cards dialogue.
Sample request:
{
"action": "guiAddCards",
"version": 6,
"params": {
"note": {
"deckName": "Default",
"modelName": "Cloze",
"fields": {
"Text": "The capital of Romania is {{c1::Bucharest}}",
"Extra": "Romania is a country in Europe"
},
"tags": [
"countries"
],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/EU-Romania.svg/285px-EU-Romania.svg.png",
"filename": "romania.png",
"fields": [
"Extra"
]
}]
}
}
}
Sample result:
{
"result": 1496198395707,
"error": null
}
guiEditNote
guiCurrentCard
guiStartCardTimer
guiShowQuestion
guiShowAnswer
guiAnswerCard
guiUndo
guiDeckOverview
guiDeckBrowser
guiDeckReview
guiExitAnki
guiCheckDatabase
Media Actions
storeMediaFile
-
Stores a file with the specified base64-encoded contents inside the media folder. Alternatively you can specify a
absolute file path, or a url from where the file shell be downloaded. If more than one of data, path and url are provided, the data field will be used first, then path, and finally url. To prevent Anki from removing files not used by any cards (e.g. for configuration files), prefix the filename with an underscore. These files are still synchronized to AnkiWeb.
Any existing file with the same name is deleted by default. Set deleteExisting to false to prevent that
by letting Anki give the new file a non-conflicting name.
Sample request (relative path):
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"data": "SGVsbG8sIHdvcmxkIQ=="
}
}
Content of _hello.txt:
Hello world!
Sample result (relative path):
{
"result": "_hello.txt",
"error": null
}
Sample request (absolute path):
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"path": "/path/to/file"
}
}
Sample result (absolute path):
{
"result": "_hello.txt",
"error": null
}
Sample request (url):
{
"action": "storeMediaFile",
"version": 6,
"params": {
"filename": "_hello.txt",
"url": "https://url.to.file"
}
}
Sample result (url):
{
"result": "_hello.txt",
"error": null
}
retrieveMediaFile
getMediaFilesNames
getMediaDirPath
deleteMediaFile
Miscellaneous Actions
requestPermission
-
Requests permission to use the API exposed by this plugin. This method does not require the API key, and is the
only one that accepts requests from any origin; the other methods only accept requests from trusted origins,
which are listed under webCorsOriginList in the add-on config. localhost is trusted by default.
Calling this method from an untrusted origin will display a popup in Anki asking the user whether they want to
allow your origin to use the API; calls from trusted origins will return the result without displaying the popup.
When denying permission, the user may also choose to ignore further permission requests from that origin. These
origins end up in the ignoreOriginList, editable via the add-on config.
The result always contains the permission field, which in turn contains either the string granted or denied,
corresponding to whether your origin is trusted. If your origin is trusted, the fields requireApiKey (true if
required) and version will also be returned.
This should be the first call you make to make sure that your application and Anki-Connect are able to communicate
properly with each other. New versions of Anki-Connect are backwards compatible; as long as you are using actions
which are available in the reported Anki-Connect version or earlier, everything should work fine.
Sample request:
{
"action": "requestPermission",
"version": 6
}
Samples results:
{
"result": {
"permission": "granted",
"requireApiKey": false,
"version": 6
},
"error": null
}
{
"result": {
"permission": "denied"
},
"error": null
}
version
apiReflect
-
Gets information about the AnkiConnect APIs available. The request supports the following params:
scopes - An array of scopes to get reflection information about.
The only currently supported value is "actions".
actions - Either null or an array of API method names to check for.
If the value is null, the result will list all of the available API actions.
If the value is an array of strings, the result will only contain actions which were in this array.
The result will contain a list of which scopes were used and a value for each scope.
For example, the "actions" scope will contain a "actions" property which contains a list of supported action names.
Sample request:
{
"action": "apiReflect",
"params": {
"scopes": ["actions", "invalidType"],
"actions": ["apiReflect", "invalidMethod"]
},
"version": 6
}
Sample result:
{
"result": {
"scopes": ["actions"],
"actions": ["apiReflect"]
},
"error": null
}
sync
getProfiles
loadProfile
multi
exportPackage
importPackage
reloadCollection
Model Actions
modelNames
modelNamesAndIds
modelFieldNames
modelFieldDescriptions
modelFieldFonts
modelFieldsOnTemplates
createModel
-
Creates a new model to be used in Anki. User must provide the modelName, inOrderFields and cardTemplates to be
used in the model. There are optional fields css and isCloze. If not specified, css will use the default Anki css and isCloze will be equal to False. If isCloze is True then model will be created as Cloze.
Optionally the Name field can be provided for each entry of cardTemplates. By default the
card names will be Card 1, Card 2, and so on.
Sample request
{
"action": "createModel",
"version": 6,
"params": {
"modelName": "newModelName",
"inOrderFields": ["Field1", "Field2", "Field3"],
"css": "Optional CSS with default to builtin css",
"isCloze": false,
"cardTemplates": [
{
"Name": "My Card 1",
"Front": "Front html {{Field1}}",
"Back": "Back html {{Field2}}"
}
]
}
}
Sample result
{
"result":{
"sortf":0,
"did":1,
"latexPre":"\\documentclass[12pt]{article}\n\\special{papersize=3in,5in}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amssymb,amsmath}\n\\pagestyle{empty}\n\\setlength{\\parindent}{0in}\n\\begin{document}\n",
"latexPost":"\\end{document}",
"mod":1551462107,
"usn":-1,
"vers":[
],
"type":0,
"css":".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n background-color: white;\n}\n",
"name":"TestApiModel",
"flds":[
{
"name":"Field1",
"ord":0,
"sticky":false,
"rtl":false,
"font":"Arial",
"size":20,
"media":[
]
},
{
"name":"Field2",
"ord":1,
"sticky":false,
"rtl":false,
"font":"Arial",
"size":20,
"media":[
]
}
],
"tmpls":[
{
"name":"My Card 1",
"ord":0,
"qfmt":"",
"afmt":"This is the back of the card {{Field2}}",
"did":null,
"bqfmt":"",
"bafmt":""
}
],
"tags":[
],
"id":1551462107104,
"req":[
[
0,
"none",
[
]
]
]
},
"error":null
}
modelTemplates
modelStyling
updateModelTemplates
updateModelStyling
findAndReplaceInModels