- Sample code
- Authentication
- Data format and error handling
- Embedding guide
- Custom document viewer page
- Tutorial
Sample code
Before starting with the API, you need to have access to a local Annotate installation; see Annotate Server Installation Guide for details or get in touch. You can use the API samples from any machine with web access to your annotate server.
- For server versions 6.0 and later, download: api-sample-code-6.0.zip
The sample code demonstrates how to use the various API calls from PHP; there is also sample Java source for accessing the API. The test PHP samples (test_createAccount.php, etc) are intended to be run from the command line, and the HTML samples (html_loginAs.php, etc) should be run from a web browser, so it is useful to extract in a web area: e.g.
% cd /var/www/annotate # ... or your web area % unzip api-sample-code-6.0.zip # ... extracts to the "api/" subfolder
You should then be able to view the API sample instructions by pointing your web browser somewhere like: http://localhost/annotate/api/index.html For production use, you will want to restrict access to this api directory (e.g. using .htaccess or moving it elsewhere). The rest of this reference guide describes the API security model and lists the available API functions. There is also a short tutorial available here.
Authentication
Each API request needs to be signed by the api-user using a secret api-key. The api user is the email address of the administrator Annotate account (on standalone installations), or the group admin user (for group accounts on annotate.com). The api key is shown in the advanced section of your Annotate account page.
Requests can be made by the api user to view the documents of a particular annotate user as long as the api user has permission. The request signature is a list of HTTP GET parameters to add to the request, e.g. to list the documents of user 'jill@example.com':
http://yoursite.com/annotate/php/listDocuments.php? api-user=joe@example.com # The admin user for the account &api-requesttime=123456 # the Unix timestamp (GMT) &api-annotateuser=jill@example.com # The user's account &api-auth=xyz1234543983jeflgnwefgdgd # The signed hash code.
The request time is the Unix timestamp (seconds since Jan 1st 1970), and requests expire after a few minutes. The api-auth code is a Base-64 encoded HMAC-SHA1 digest of the string:
$phpfn . "\n". $apiuser. "\n". $requesttime. "\n". $annotateusersigned using the secret api-key. The authentication algorithm is similar to that used for signing Amazon S3 requests, so you may be able to adapt the sample code for your preferred programming language from the Amazon developer site. A PHP function which implements it is shown below: (see the Crypt_HMAC() documentation; this function is included in the sample code.
// ==== Pseudocode ===== # Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( StringToSign ) ) ); // ==== PHP sample code ==== function signRequest( $phpfn, $apiuser, $apikey, $annotateuser ) { $requesttime = time(); $stringToSign = "$phpfn\n$apiuser\n$requesttime\n$annotateuser"; $hasher =& new Crypt_HMAC($apikey, "sha1"); $signature = hex2b64($hasher->hash($stringToSign)); return "api-user=".rawurlencode($apiuser). "&api-requesttime=".$requesttime. "&api-annotateuser=".rawurlencode($annotateuser). "&api-auth=".rawurlencode($signature); }
The authentication mechanism in Java is similar:-
import sun.misc.BASE64Encoder; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.net.URLEncoder; import java.util.Date; import java.net.URL; import java.io.*; // Make a base64 encoded HMAC / SHA1 hash of a string. public static String sign(String apikey, String data) throws Exception { Mac mac = Mac.getInstance("HmacSHA1"); byte[] keyBytes = apikey.getBytes("UTF8"); SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1"); mac.init(signingKey); byte[] signBytes = mac.doFinal(data.getBytes("UTF8")); String signature = (new BASE64Encoder()).encode(signBytes).replaceAll("\n",""); return signature; } public static String signRequest( String phpfn, String apiuser, String apikey, String annotateuser, long validfor) throws Exception { long requesttime = (new Date()).getTime() + validfor; String stringToSign = phpfn + "\n" + apiuser+ "\n"+ requesttime + "\n" + annotateuser; String signature = sign(apikey, stringToSign); return "api-user=" + URLEncoder.encode(apiuser, "UTF-8") + "&api-requesttime=" + URLEncoder.encode(""+requesttime, "UTF-8") + "&api-annotateuser=" + URLEncoder.encode(annotateuser, "UTF-8") + "&api-auth=" + URLEncoder.encode(signature, "UTF-8"); }
Data format and error handling
Structured data is returned from requests in Javascript Object Notation (JSON) format. This is a simple language independent data interchange format with libraries for all major languages (see www.json.org), and is a simpler and more efficient alternative to XML.
If there is an error with the request (e.g. with authentication), the return value from the GET request will be the string "ERR" + an error message, otherwise it will return a valid JSON string. You can test the response value with code like:
// Sample PHP code for testing the API response $req = signRequest("listDocuments.php", "joe@example.com", "...your-secret-api-key...", "jill@example.com"); $txt = file_get_contents("http://your.server.com/annotate/php/listDocuments.php?".$req); if (substr($txt, 0, 3) == "ERR") { print "Problem with request: $txt\n": } else { // OK, parse as JSON object: $obj = json_decode($txt); print_r($obj); }
Embedding guide
This section includes instructions for embedding an Annotate panel within your own application. It assumes you have already installed a local copy of Annotate. There is a 'html_sample-proof.php' page included here which demonstrates how to embed an Annotate view of a PDF panel in an iframe.
How it works
The sample at 'api-sample-code/php/html_sample-proof.php' includes an example which you can use as a starting point; the sample is in PHP, but you can use any web scripting language to embed an Annotate panel (ASP, JSP, Perl, Python etc).
The sample first does a HTTP GET to upload a file, then embeds an iframe into the page which points to the API call that will create the user account if necessary, log the user in and display the document. To integrate it with your own system, you would want to pass parameters such as the link to the file and the email of the user who will make the notes. Both requests will need to be signed as indicated in the Authentication section and shown in th sample code.
The files are uploaded to the API user's default workspace. If you need to organise the files in different workspaces, you can supply a project ID or name which represents the workspace the file will be uploaded to.
Step 1: Specify the PDF file to upload
The first step is to get your script to perform a signed HTTP GET request to 'simpleUpload.php', passing the authentication parameters, a URL link to the file to be uploaded and a number of optional parameters. These optional parameters include the option to upload the document to a given workspace, hide certain buttons in the document viewer (list of buttons and codes available here) and disable the URL caching for debugging. The response will be a link to the uploaded document which will be used in the src= link of an iframe, to be embedded in your web page.
// The sample URL below shows the GET parameters. // *NB* You need to URI encode the values (%40 inplace of @ etc) http://yoursite.com/annotate/php/simpleUpload.php? api-user=joe@example.com # The admin user for the account &api-requesttime=123456 # the Unix timestamp (GMT) &api-annotateuser=jill@example.com # The user's account &api-auth=xyz1234543983jeflgnwefgdgd # The signed hash code. &url=http://test.nnotate.com/php/test.pdf # Replace with URL of your file &projectid=abc123 # (optional) specify a workspace for the doc to be uploaded to &nocache=0 # (optional) set to 1 if you want subsequent GETs to reupload &hide="nto-dnl" # (optional) list of GUI components to hide, separated by '-' // Fetch the result from an HTTP GET of the above URL // The response will contain the plain text string "OK " + a link relative to the uploaded document OK pdfnotate.php?d=2015-01-01&c=abcdef&ws=123456 // or, if there was a problem uploading the PDF it will return: ERR {error message}
A note on caching
The 'simpleUpload.php' API call will first check whether the given URL has already been uploaded to the account, and if it has it will return the link immediately without reuploading the PDF. You can change this behaviour (e.g. for debugging) by setting the 'nocache=1' flag.
The 'simpleUpload.php' API call will first check whether the given URL has already been uploaded to the account, and if it has it will return the link immediately without reuploading the PDF. You can change this behaviour (e.g. for debugging) by setting the 'nocache=1' flag.
Step 2: Use the upload's response to build the src= link of an iframe
The src= link of the iframe will point at the 'loginAs.php' API call, which will allow a given user to view the document and make notes. It will first create the user account if it doesn't exist, log the user in and give access to the document by adding the user to the workspace.
The request will be signed as before, with the 'annotateUser' parameter being the email of the user who will be logged in. The 'pdfnotate.php?...' link returned above will also be supplied, along with the parameters that give access to the user and optional parameters for the creation of the account.
// The sample URL below shows the GET parameters. // *NB* You need to URI encode the values (%40 inplace of @ etc) http://yoursite.com/annotate/php/loginAs.php? api-user=joe@example.com # The admin user for the account &api-requesttime=123456 # the Unix timestamp (GMT) &api-annotateuser=jill@example.com # The user's account &api-auth=xyz1234543983jeflgnwefgdgd # The signed hash code. &loc=pdfnotate.php?d=2015-01-01&c=abcdef # Link to the doc returned on upload (URL encoded) &add=1 # Add user to the workspace to access the doc &ws=123456 # Workspace ID, returned in the first call &role=3 # Workspace's role ID, permission to annotate &create=1 # (optional) create account &firstname=jill # (optional) &lastname=smith # (optional) &sig=jill # (optional) signature used for every note
Custom document viewer page
The link to pdfnotate.php can have optional extra parameters to hide some of the buttons, if you don't need them for your application. To hide particular buttons, add the parameter 'hide' with a list of the things to hide, separated by '-'. The codes for the possible items in the hide string can be found below.
It is also possible to set server-wide hide options, by adding them to the phpconfig.inc file:
// Hide the home button and the 'sign out' option: $defaultHide = "gti-sgo";
Full list of codes for hiding GUI components
gti : Annotate logo (link to document index page) pch : Left-hand side bar cht : Chat button within the sidebar nod : Notes button within the sidebar fdt : Notes tab - Filter - date section ftg : Notes tab - Filter - tags section fau : Notes tab - Filter - authors section pod : Thumbnails button within the sidebar noa : 'View-only mode' icon (when document closed for new notes) flb : File menu vwb : View menu fht : Freehand button wnb : Window menu tlm : Tools menu zdh : Help button stm : Metadata option tgs : Document tags option dnl : Download option prn : Print option mtf : Export option sha : Share option zio : Zoom in/out options fwp : Fit width/page options rpm : Rotate page option fwb : Find option bkm : Bookmarks option mtc : Clipboard option dcb : Document breadcrumbs and title dbc : Only document breadcrumbs, show document title ntf : Notifications icon usr : Username dropdown uhm : Home link within username dropdown ush : Share with me link within username dropdown ust : Settings link within username dropdown uso : Sign out link within username dropdown Note dialog msc : mark style chooser (border colour and shape for graphical notes and text annotation type for text annotations, finer tune available, see below) ntc : Note To: chooser ttr : tag editor tgc : tag chooser and editor ltb : Link to button nrb : Disable note reply button Note dialog for text highlights sl + style id: hide certain text annotation style options List of style ids h : highlight u : underline i : insert s : strikethrough e : edit e.g. "slh" for highlight, "slh-slu" for highlight and underline
Setting initial zoom percentage
To set the initial zoom percentage, set initzoom to the percentage. There is a minimum zoom scale of 25% and a maximum of 150%. e.g. to start at 75% -
pdfnotate.php?d=...&c=...&initzoom=75 start as 'fit width' pdfnotate.php?d=...&c=...&initzoom=w
Opening on a page, a note, or the index view
To open a document at a particular page, or with a particular note highlighted, you can append a fragment to the URL like:
To open on the note index page: pdfnotate.php?d=...&c=...#notes To open on a given page number: pdfnotate.php?d=...&c=...#page5 To open on a given page number with a note highlighted: pdfnotate.php?d=...&c=...#page5_note4
Setting initial note display style
To set the initial note display style, use the parameter nds to one of 'm' - margin, 'b' - box, 'f' - footer or 'h' - hidden. e.g. to start with margin notes:
pdfnotate.php?d=...&c=...&nds=m
Tutorial
This guide covers the essentials of the Annotate API. It demonstrates how to create a workspace, upload a document to it, create user accounts and finally add them to the workspace. Sample code is available here, see 'test_tutorial.php', which is meant to be run from the command line.
Step 1: Creating a workspace
The workspace must be created by a fully licensed user, as only these can create workspaces. For the purpose of this tutorial, the owner will be the api-user, so his email will be supplied as the annotate-user parameter. The POST request looks as follows:
http://yoursite.com/annotate/php/apiCreateWorkspace.php? api-user=joe@example.com # The admin user for the account &api-requesttime=123456 # the Unix timestamp (GMT) &api-annotateuser=joe@example.com # The user's account &api-auth=xyz1234543983jeflgnwefgdgd # The signed hash code. HTTP POST parameters: &name=Test workspace # the name for the new workspace
On success, the response will look like "OK 115500865". This is the workspace ID which must be supplied when uploading documents to Annotate.
Step 2: Uploading a document to the newly created workspace
The annotate-user supplied must have uploading permissions within that workspace. Permissions are controlled through workspace roles. We will use the api-user, which was used to create the workspace and therefore has all permissions. You can grant all permissions to additional workspace members by assigning them the role 'Admin' within that workspace.
There are several ways to upload a document, as described in the Upload document section. We will supply a URL of a sample document.
<form method='POST' action='uploadDocument.php? api-user=joe@example.com &api-requesttime=123456 &api-annotateuser=joe@example.com &api-auth=xyz1234543983jeflgnwefgdgd'> <input name='ws' value='115500865'> # the workspace ID <input name='url' value='http://www.textensor.com/enhancing-documents-2007.pdf'> <input name='urlfilename' value='sample.pdf'> # (optional) filename to use </form>
On success, the response will look like "OK 2016-09-30 mdfZ0n1v". The date and code pair will uniquely identify the document. A list of documents uploaded to a given workspace can be retrieved using listDocuments.php
Step 3: Creating a user account
User accounts on your local Annotate server can be fully licensed or annotating users, the former of which are able to create workspaces and upload documents.
We will use createAccount.php, which will create an annotating user account. The user can be upgraded using updateAccount.php.
http://yoursite.com/annotate/php/createAccount.php? api-user=joe@example.com # The admin user for the account &api-requesttime=123456 # the Unix timestamp (GMT) &api-annotateuser=new678@example.com # The user's account &api-auth=xyz1234543983jeflgnwefgdgd # The signed hash code.
On success, the response will look like "OK - created account for new678@example.com".
Step 4: Adding new user to the workspace
Only workspace members are able to access the documents within it. A user can be added using apiUpdateWorkspaceUsers.php. Besides the workspace ID, it is necessary to supply the role ID which will be assigned to the user and will determine his permissions. A list of workspace roles can be retrieved using apiGetWorkspaceDetails.php.
http://yoursite.com/annotate/php/apiUpdateWorkspaceUsers.php? api-user=joe@example.com # the admin user for the account &api-requesttime=123456 # the Unix timestamp (GMT) &api-annotateuser=joe@example.com # the api-annotateuser has to match the apiuser &api-auth=xyz1234543983jeflgnwefgdgd # the signed hash code. HTTP POST parameters: &ws=115500865 # the workspace to be updated &action=add # the action to be performed &email=new678@example.com # the user's email &roleid=3 # workspace role id, see apiGetWorkspaceDetails.php
On success, the response will look like "OK 2 added user724@example.com". "2" is the ID of the user within the workspace.
Note: Steps 3 and 4 can also be done on the fly using loginAs.php.