Indian Kanoon API Documentation
Introduction
Access Point: API services are available from the webserver http://api.indiankanoon.org. There are four kind of API requests that can be accessed are available at the following end points:
Search query
https://api.indiankanoon.org/search/?formInput=<query>&pagenum=<pagenum>
Document
https://api.indiankanoon.org/doc/<docid>/
Document fragments
https://api.indiankanoon.org/docfragment/<docid>/?formInput=<query>
Document Metainfo
https://api.indiankanoon.org/docmeta/<docid>/
The results can be obtained in JSON format or in XML format by specifying it in the HTTP Accept header. It is the responsibility of the API user to construct an HTML page with their own styling if they wish to display it to their users. We will provide sample code to construct HTML page from the API results.
The pagenum in Search starts with zero and not one.
Authentication: Requests to the API services can be authenticated either using the shared API token that you can generate on the website itself or thorugh the public-private crypto in which the customer uploads their public key to the API services and then sign each request using their private key.
You can use the shared API token or the public-private key system and even mix them. The API services would verify the Token or the signature in public-private key crypto system and then only return the results. In case the verification fails, a 403 error is returned.
Deployment:
When using the API Token, you can forward the user requests to the API services with the API Token in the HTTP header. The server will return the result in JSON or XML format (as requested) and then you can create a webpage and send it back to the user.
When using the public-private key crypto system, you should create four endpoints "/search/", "/doc/", "/docfragment/" and "/docmeta/" on your own domain or a subdomain. When a user of your website sends a document id or search query to your website, your endpoints create a unique message and sign that message using your private key. Send the message and the signature to the user with a Javascript code that POSTS to api.indiankanoon.org using AJAX. The result obtained on completion of the AJAX request should be then constructed into an HTML fragment and added to a placeholder div (using javascript. Sample code using Jquery here).
As you can see the API Token approach is much simpler than the public-private key crypto. On the other hand, in public-private key system, your servers will not be fetching any results. All fetching will be done by the clients themselves.
API Details
In case of API Token, your just need to add the Authorization header in the HTTP request. If your API token is 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b, you can send the following HTTP header with each request:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
In case of public-crypto system, following HTTP headers are required in each request to the API:
X-Customer: email-id
X-Message: a unique message encoded in base64 encoding
Authorization: HMAC <X-Message is signed using private key of the X-Customer and base 64 encoded>
X-Customer refers to the email-id that you have registered with the API services. X-Message could be any unique string for a request. It could be a UUID string or a string generated by the concatenation of client IP address, current timestamp and the request URL. The API services would drop any request with duplicate message to prevent against replay-uses. Lastly, the "Authorization" header is the string "HMAC" followed by the signature after signing X-Message with your private key. "HMAC" is an indication of public-private key crypto that we use.
X-Message and Authorization headers have to be base64 encoded in order to be used in an ASCII protocol like HTTP. Here is a sample code to encode message and signature using base64 method:
from base64 import b64encode
encoded_message = b64encode(message) # message is a binary string
encoded_signature = b64encode(signature) # siganature is computed as above
Public-Private Key Authentication
The "API Services" can verify each request using Public-Private Key Cryptography. The benefit of using Public Key cryptography is that the customer need not trust IKanoon for correct accounting. And until and unless the private key of the customer is stolen, it is safe and secure from all security attacks.
Generating Public-Private Key Pair
The first step in public private key cryptography is to generate such a pair. You should generate your key pair and then upload the public key to the API Services. You should not disclose the private key to anyone other than to sign requests on your webserver. The API services will not be generating the key pair on your behalf as you do not need to trust the API services for correct accounting.
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
Signing message with private key
The Authorization header contains a signed certificate of the unique message with each request. The API user signs the message using its private key. Here is the sample code for signing the message:
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
def get_private_key():
key = open(<path-to-private_key.pem>, 'r').read()
private_key= RSA.importKey(key)
return private_key
def sign_message(message):
private_key = get_private_key() # you may cache the key
signer = PKCS1_v1_5.new(private_key)
digest = SHA256.new(message)
return signer.sign(digest)
AJAX Approach
The customer of API services should just sign the request and send a javascript code to its user to send the actual request to the API services. Here is the jquery code that is sent to the users. The code automatically contacts the API services with the specified URL, customer email address, X-Message and the signature. The result obtained is then added to the html div in the page. Look at the complete_fn function to see how various fields in the JSON response can be used to construct the HTML page.
//div to hold result of AJAX request
<div id="ikresult"><div>
//load jquery
<script TYPE="text/javascript" SRC="jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var apiurl = <IK API url>;
var headers = {'X-Customer': <customer-email-id>,
'X-Message': <base64 encoded unique message>,
'Authorization': HMAC <base64 encoded signed message>};
// for adding document
// the json result obtained has the document as doc
var complete_fn =
function (jsonObject) {
var jsonResponse = jsonObject.responseJSON;
html_data = jsonResponse.doc;
$("#ikresult").append(html_data);
};
// for adding document fragment
var complete_fn =
function (jsonObject) {
var jsonResponse = jsonObject.responseJSON;
html_data = '<div class="title">Showing document fragments containing the query <b>' +
jsonResponse.formInput + '</b> in ' + jsonResponse.title + '</div>';
html_data += '<div><a href="/doc/' + jsonResponse.tid +
'/>View complete document</a></div>';
html_data += '<div class="headline">' + jsonResponse.headline + '</div>';
$("#ikresult").append(html_data);
};
// for adding search results
var complete_fn =
function (jsonObject) {
var jsonResponse = jsonObject.responseJSON;
var docs = jsonResponse.docs;
var categories = jsonResponse.categories;
var formInput = jsonResponse.encodedformInput;
var html_data = '<div class="found"><b>' + jsonResponse.found + '</b></div>';
html_data += '<div class="results">';
for (var i = 0; i < docs.length; i++) {
var doc = docs[i];
html_data += '<div class="result"><a href="/docfragment/'+ doc.tid +
'/?formInput=' + formInput + '">' + doc.title+ '</a><div class="fragment">'
+ doc.headline + '</div><div class="docsource">' + doc.docsource+
'</div></div>';
}
html_data += '</div><div class="categories">';
for (var i = 0; i < categories.length; i++){
category = categories[i];
html_data += '<div class="categories">' + category[0];
for (var j = 0; j < category[1].length; j++) {
html_data += '<div><a href="/search/?formInput=' + category[1][j].formInput +
'">' + category[1][j].value + '</a></div>';
}
html_data += '</div>';
}
html_data += '</div>';
$("#ikresult").append(html_data);
};
var settings = {url: apiurl, headers: headers, dataType: "json",
complete: complete_fn, type: "POST", };
$.ajax(settings);
});
</script>
API Parameters
API Parameters refer to query parameters in the URL that can be used to customize the result that will be obtained.
Search API
Parameter
Meaning
formInput
This is the query to the search API. It can consist of words and phrases and the words can also be separted by various operators. For phrases, enclose a set of words by quotation marks. For example, in order to search for phrase freedom of speech in the document text, you need to send formInput="freedom of speech" as query parameter to the search API.
Operators: Beside phrase search, words can be combined by ANDD, ORR and NOTT opertors. So a search for 'murder ORR kidnapping' will search for documents that have either the word 'murder' or the word 'kidnapping'. Similarly, a search for 'murder ANDD NOTT kidnapping' will look for documents that have the word 'murder' but not the word 'kidnapping'. ANDD is implicit when used with a series of words. So 'murder kidnapping' is effectively 'murder ANDD kidnapping'. Note that the operators ANDD, ORR and NOTT are case sensitive and require at least one space at both start and end.
doctypes
By default, Indian Kanoon will query all documents and try to find out the most appropriate documents related to your query. However, if you are interested in only a certain set of documents then you can use the doctypes filter to narrow your search. The doctypes value for individual courts are supremecourt, delhi, bombay, kolkata, chennai, allahabad, andhra, chattisgarh, gauhati, jammu, srinagar, kerala, lucknow, orissa, uttaranchal, gujarat, himachal_pradesh, jharkhand, karnataka, madhyapradesh, patna, punjab, rajasthan, sikkim, kolkata_app, jodhpur, patna_orders, meghalaya. For delhi district courts it is delhidc. For tribunals it is aptel, drat, cat, cegat, stt, itat, consumer, cerc, cic, clb, copyrightboard, ipab, mrtp, sebisat, tdsat, trademark, greentribunal, cci.
You can also use set of documents as value for doctypes. For example you can also use tribunals (for all the tribunals), judgments (for SC, HC, District Courts), laws (Central Act and Rules). In fact, you can comma separate any court or aggregator value with doctypes filter. For example, doctypes=highcourts,cci will search in all high courts and the tribunal CCI (Competition Commission of India).
fromdate
Normal search will look for documents on all possible dates. You can restrict it to the minimum possible date by specifying it in DD-MM-YYYY format. For example: fromdate=1-10-2016 will only search for documents that were published after 1st October 2016.
todate
Normal search will look for documents on all possible dates. You can restrict it to the maximum possible date by specifying it in DD-MM-YYYY format. For example: todate=1-10-2016 will only search for documents that were published till 1st October 2016.
title
You can put any words or phrases in this paramater and a document will match only if those words and phrases are present in the title of the document. For example, to only look for documents that have kesavananda in the title, one can use the following parameter and value in the search API title=kesavananda.
cite
You can use this filter to restrict search to only documents that have a specific citation. For example, to search only for documents that have 1993 AIR citation you can usecite=1993 AIR parameter in search API.
author
In order to restrict to judgments that are written by a particular judge, one can use the author parameter. For example, to look for judgments written only by arijit pasayat, type author=arijit pasayat
bench
It allows you to restrict judgments that have only the given judge in the bench. For example, to find judgments in which "Arijit pasayat" has been on the bench, use bench=arijit pasayat in the search API.
maxcites
Sometimes it may be useful to get the list of citations for each matching document in the Search API itself. You can use the maxcites parameter to get the list of citations for the matching documents. For example, /search/?formInput=culpable+homicide&maxcites=20 will give you upto 20 citations for each document matching the query culpable homicide. The maximum number of citations for each document is capped at 50.
pagenum
pagenum=0 in the search API will give you the 1st page. For further pages you can increase the page number.
maxpages
You can get more than one page in a single search API call. For example, maxpages=50 in the search API will give you up to 50 pages in one API call itself starting from the pagenum value. You will be charged for only the number of pages that are returned irrespective of the maxpages value. For example, if you set up maxpages at 50 and you only get 7 pages of results, you will be charged for Rs. 3.50 only. Also not that you cannot fetch more than 1000 pages through the API.
Size of Document in Search API: When you will use the search endpoint, each search sesult will have docsize value. It is the size of the document in terms of the number of characters. You can use this value to decide whether you want to fetch that document.
Document API
Citations in Document API: When you call the document API endpoint, you will get the top five document it cites in citeList and the top five documents that it is cited by in citedbyList. However, you can get more cites and citedby in a single call to the document API. You can get up to 50 cites and citedby by specifying maxcites and maxcitedby in the document API. For example, /doc/<doc-id>/?maxcites=10&maxcitedby=20 will get the list of size upto 10 in citeList and upto 20 in citedbyList.