Documents and Notes

Upload document

The uploadDocument.php call lets you do a HTTP POST to upload a document to the Annotate server and add it to a workspace. The annotateuser must be an owner of the workspace or have upload permissions through an admin, user or custom role. The URL should include the normal GET parameters, with the other fields as POST parameters. To post a file, use multipart/form-data as with standard HTML form file uploads. The sample here is given as an HTML form, but you can also simulate a form HTTP POST call from scripting languages, or use a HTTP utility such as CURL.

<form method='POST' enctype='multipart/form-data' action='uploadDocument.php?
      api-user=joe@example.com           
      &api-requesttime=123456            
      &api-annotateuser=jill@example.com  
      &api-auth=xyz1234543983jeflgnwefgdgd'>

     <input name='ws'>                       # the workspace ID
     <input name='desc'>                     # (optional) the description
     <input name='tags'>                     # (optional) comma separated list of tags

     # option 1: include a file browse component:
     <input type='file' name='Filedata'>    

     # option 2: provide the URL of the document to fetch
     <input name='url'>                   
     <input name='urlfilename'>              # (optional) filename to use

     (optional: replace document with newer version and keep existing notes)
     <input name='replace'>                  # e.g. 2011-01-01/abc123
</form>

You can either upload a file by posting it (a normal file upload), or by providing the URL of the document to fetch in the url parameter.

The default return value is "OK {document date} {document code}", or "ERR " + an error message, e.g.:

OK 2008-01-02 abc123

There are alternative return formats (see subsections below) which may be useful if you are running annotate on a different web server from your web application.

You can make a link to the uploaded document using a url like:

pdfnotate.php?d=2008-01-02&c=abc123

- see also the loginAs call which lets you create a link to log in as a given user and display a document. The user must have been added to the workspace - you can do it on the fly using the optional 'add=1', 'ws', 'role' URL parameters in the loginAs call.

To control detailed settings of the displayed document, e.g. hiding particular buttons in the interface, opening on a particular page or note, or with a particular zoom level, please see the embedding a PDF guide.

Upload document and redirect to given page

Instead of returning a plain text string like "OK 2009-01-01 abc123" you can get uploadDocument.php to redirect to a user supplied URL, with the date and code as GET parameters. This can be useful if you need to store the uploaded date and code in your own database, and then show the document in an iframe.

<form method='POST' target='_blank' enctype='multipart/form-data' action='uploadDocument.php?
      api-user=joe@example.com           
      &api-requesttime=123456            
      &api-annotateuser=jill@example.com  
      &api-auth=xyz1234543983jeflgnwefgdgd'>

     <input type='hidden' name='fmt' value='redir' />
     <input type='hidden' name='loc' value='http://yoursite.com/yourscript.php?arg123=abc' />
     <input type='hidden' name='errloc' value='http://yoursite.com/yourerrscript.php?arg456=def' />

     <input name='ws'>                       # the workspace ID
     <input name='desc'>                     # the description
     <input name='tags'>                     # comma separated list of tags

     # option 1: include a file browse component:
     <input type='file' name='Filedata'>    

     # option 2: provide the URL of the document to fetch
     <input name='url'>                   
  <form>

When the upload has completed, it will do a redirect to the url supplied in the loc post parameter, e.g.:

http://yoursite.com/yourscript.php?arg123=abc&d=2009-01-01&c=abc123&status=OK&annotateuser=jill@example.com
-or-											
http://yoursite.com/yourerrscript.php?arg456=def&errmsg=...&status=ERR&annotateuser=jill@example.com

You can use the return values to show the document in an iframe. Note that the redirect is performed by uploadDocument.php generating a simple html web page which uses javascript to set document.location = ... It uses this technique in preference to a HTTP redirect as a work-around for Microsoft Internet Explorer's implementation of iframes.

Upload document and call script in parent window

As another alternative callback mechanism, you can get uploadDocument.php to generate a javascript callback to your application, providing the document's date and code. Browsers typically allow iframes to call javascript methods in the parent window, even if the iframe is loaded from a different web server. If you have an iframe on your page with id iframeid, and javascript methods documentUploaded and uploadError on your page, you can add a form like:

<form method='POST' target='iframeid' enctype='multipart/form-data' action='uploadDocument.php?
      api-user=joe@example.com           
      &api-requesttime=123456            
      &api-annotateuser=jill@example.com  
      &api-auth=xyz1234543983jeflgnwefgdgd'>

     <input type='hidden' name='fmt' value='js' />
     <input type='hidden' name='cb' value='parent.documentUploaded' />
     <input type='hidden' name='errcb' value='parent.uploadError' />

     <input name='ws'>                       # the workspace ID
     <input name='desc'>                     # the description
     <input name='tags'>                     # comma separated list of tags

     # option 1: include a file browse component:
     <input type='file' name='Filedata'>    

     # option 2: provide the URL of the document to fetch
     <input name='url'>                   
  <form>

When the upload is completed, it will call back one of the javascript functions you supply in the cb or errcb fields, e.g.

// Callbacks on finishing uploading.
function documentUploaded(date, code, user) {
  alert('Document uploaded ok: ' + date + ' ' + code + ' ' + user);
}
function uploadError(errmsg) {
  alert('Document upload error: ' + errmsg);
}

Update metadata

The updateDocumentMeta.php call lets you modify a document's metadata (title, tags, authors). It uses HTTP POST for the metadata; the document to use is specified by the date and code in the request URL:

http://yoursite.com/annotate/php/updateDocumentMeta.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 annotate user
    &api-auth=xyz1234543983jeflgnwefgdgd   # The signed hash code.    

    &d=2008-01-02                          # The document upload date
    &c=abc123                              # the document code

POST parameters:
   title              # Document title
   authors            # authors
   notes              # Notes on the document as a whole
   tags               # Document level tags

   ref                # (optional) a user id for the document (e.g. ref#, invoice# etc)
   doctypeid          # (optional) an integer ID for the workspace document type

The return value is "OK" or "ERR {error message}". There are a number of optional POST parameters to the updateDocumentMeta.php call - these are described below. If the extra parameters are not included in the call, the settings will not be modified.

Advanced document metadata flags

There are a number of optional settings on a document, which can be used to control who is authorized to add comments, down to the level of individual pages.

Optional POST parameters for updateDocumentMeta.php:
   defaultNoteStatus     # shared / private / feedback
                         # The default setting for new notes.

   allowNoteStatusChange # 1 / 0
                         # Whether to allow users to change the status.

   allowNewNoteTags      # 1 / 0
                         # Whether to allow users to add new tags.

   closedForComments     # 1 / 0
                         # If set, don't allow new comments

   addToContacts         # 1 / 0
                         # If set, add new document viewers to 
                         # contacts list of doc owner

   linkSharable          # 1 / 0  
                         # If set, enable access to document
                         # to anyone with a link

Update permissions

It is also possible to control which users are permitted to annotate a document, and optionally set the allowed page ranges.

Optional POST parameters for updateDocMeta.php:
   allowAnnotationUsers    # comma or \n separated list of user emails
                           # e.g. for nobody except joe and jane:
                           # "_none,joe@example.com,jane@example.com"

   denyAnnotationUsers     # comma or \n separated list of user emails
                           # e.g. "badguy@example.com,badgal@example.com"
                           
# Special values for entries in the allow / deny lists:
#   "_any"  --- any user with access to document
#   "_none" --- no user
# the allow list is processed first, then deny.
# allow defaults to all users allowed, so to restrict to set users use 
# "_none" first:
# e.g.  allowAnnotationUsers : "_none, joe@example.com, jane@example.com"
#

To control whether particular users can annotate particular pages of a document, set the perPagePermissions list. The perPagePermissions list overrides the settings in the allowAnnotationUsers list, so just set one or the other, or the allow list will be ignored. The denyAnnotationUsers list can be used in conjunction with perPagePermissions though - it is checked afterwards and trumps the perPagePermissions settings to block particular users.

Optional POST parameters for updateDocMeta.php:
   perPagePermissions      # one entry per line, format as below:

# Format one entry per line, each entry is {user email}:{page range}\n
# Special values for the user field are: 
#   _any
#   _none
# The page range is specified as a comma-separated list of 
# page numbers; ranges like "10-20" can be included in the list.
# and an item can be prefixed by "!" to exclude that page. 
# To match any page, use "1-".
# Note that the page numbers are those of the PDF file
# starting at 1 - 
# If perPagePermissions is set, there is an implied: "_none:1-"
# rule preceeding any user rules. 

# Example page ranges:
  1,2,10-20     -- pages 1, 2 and 10-20 only
  1-,!22        -- any page apart from 22
  1-50,!10-20   -- equivalent to 1-9,21-50
  50-           -- pages 50 to the end of the document.
  -20           -- all pages from start to #20

#
# Items are processed in the order of the entries.
# Example values for perPagePermissions array (NB there
# is a Colon (:) separator between the user name and the 
# page range)

  joe@example.com:12
  jack@example.com:1-11,13-
  jill@example.com:1-100,!33

Some examples:

# Only joe and jill allowed to annotate the document
  allowAnnotationUsers:"_none, joe@example.com, jill@example.com"
  denyAnnotationUsers:
  perPagePermissions:

# Anyone apart from joe@example.com can annotate any page
  allowAnnotationUsers:
  denyAnnotationUsers:"joe@example.com"
  perPagePermissions:

# joe can annotate all pages, other users only pp1-10, jack blocked:
  allowAnnotationUsers:
  denyAnnotationUsers:"jack@example.com"
  perPagePermissions:"_any:1-10\njoe@example.com:1-"

# anyone can annotate all pages, but joe can't annotate page 22
  perPagePermissions:"_any:1-\njoe@example.com:!22"

# nobody can annotate any pages except joe who can annotate 1,3,5,7,9-
  perPagePermissions:"_none:1-\njoe@example.com:1,3,5,7,9-"

User defined document metadata fields [*new in v3.0.13 *]

You can store additional fields such as x_myfield in the document metadata object; any fields starting with x_ in the POST call to updateDocumentMeta.php will be stored in the metadata object.

Sample optional POST parameters for updateDocMeta.php for user defined fields:

   x_myfield: "some data item",
   x_mydatabaseid: "123456"

List documents

To fetch a list of the documents in a given workspace, use an HTTP GET call to listDocuments.php. The parameters are as below - api-annotateuser specifies the user whose documents you want to list, the api-user is the admin API user account. Details for documents uploaded in each month are returned in a separate array; you can provide 'from' and 'to' months to restrict the number of documents returned.

http://yoursite.com/annotate/php/listDocuments.php?    
	api-user=joe@example.com
	&api-requesttime=1234566
	&api-annotateuser=jill@example.com
	&api-auth=ABC123...

	&ws=123456                   # workspace ID
	&from=2008_01                # (optional) YYYY_MM
	&to=2009_01                  # (optional) YYYY_MM
	&withmeta=0                  # (optional) include metadata for each document
	&withnotes=0                 # (optional) include notes on each document
	&p=                          # (optional) filter by parent folder ID

The return value is an array (by month) of arrays (by document) of basic document information:

[ // outer array: list of months
	[   // list of document metadata for 1st month
		{    // document info for a single document:
			code: "abc123",
			date: "2008-01-01",
			name: "doc123.pdf",
			owner: "joe@example.com",
			type: "pdf",    // "pdf" for all uploaded documents (incl .pdf, .doc, .xls etc)
			parentid: ""   // The parent folder ID, or "" for Home folder.
		},
		{
			code: "abc456",
			date: "2008-01-02",
			name: "BBC news story"
			owner: "joe@example.com",
			type: "pdf",
			parentid: "2008-01-01/abc789"   // The parent folder id.
		}
	],
	[  // list of document metadata for 2nd month
		{
			code: // ... etc
		}
	]
]

Each document has a date (when uploaded to Annotate, format YYYY-MM-DD) and a code, a random string which allows access to the document. The owner is the email address of the person who uploaded the document. The type is always 'pdf', which is used for all documents (PDF, Word, Excel etc) which are displayed using the paginated PDF viewer. Each document can also be in a folder within a workspace - the parentid field specifies the folder id. If this is the empty string "", then the document is in the user's top level Home folder.

Link to a document

If you have fetched a list of documents, and would like to create a URL link to display a document on your Annotate server, you can create an href link like:

http://yoursite.com/annotate/php/pdfnotate.php?d=2008-01-01&c=abc123

Note: The user must have been added to the workspace to be able to see the document. You can see the workspace users using the apiGetWorkspaceDetails call and add new ones with the apiUpdateWorkspaceUsers call.

Substitute the appropriate value for the document's date and code in the parameters d= and c=. The original uploaded files for an office / pdf document are stored in a folder like:

// sample uploaded file:
http://yoursite.com/annotate/docs/2009-01-01/abc123/file123.doc

// PDF version of uploaded file:
http://yoursite.com/annotate/docs/2009-01-01/abc123/file123.pdf

// Document metadata (JSON format) for a document:
http://yoursite.com/annotate/docs/2009-01-01/abc123/docmeta.js

You can get the filename from the srcname field of the document metadata object (the name field has the filename of the PDF version). The document metadata object is available from the docmeta.js file in the document's folder; you can also fetch it using the listDocuments.php API call described in the next section.

Fetch lists of complete document metadata

To fetch the extended document metadata (the description, notes, tags, readers etc), you can set withmeta=1 in the call to listDocuments.php. For each document returned you will get an extra field "meta" containing the information. For large numbers of documents, this API request will be slower than fetching the basic information, so for scalability you may wish to restrict requests to a few months at a time.

[ // array of months
  [ // array of doc meta for a month
   {  // sample extended metadata for a document:
     name: "somefile.pdf",
     code: "zvq123",
     date: "2008-05-08",
     owner: "joe@example.com",
     parentid: "",   // parent folder id, in this case "" is the Home folder.
     meta: {
        created: "2008-05-08 13:09.19",
        title: "A paper on XYZ",
        notes: "These are some notes about the whole document...",
        tags: "paper, pdf, important",
        code: "zvq123",
        date: "2008-05-08",
        pages: 10,
        cost: 50,                                     // in credits                            
        srcext: "doc",                                // e.g. 'doc' for uploaded Word docs
        srcname: "somefile.doc",                      // name of file as uploaded
        srcsize: 123456,                              // size of uploaded file (bytes) [* new in v3.0.13 *]
        name: "somefile.pdf",                         // name of file converted to pdf (if needed)
        authors: "",                                  // value of 'authors' field in doc properties 
        owner: "joe@example.com",
        readers: 
        [
           {
            email : "jill@example.com", 
            role: "guest",
            sig:  "jill"
           } 
           // , { ... more readers of this document }
        ]
        type: "pdf",
        status: "ok",  // or "trash" for deleted documents.
        payments: [ // record of payments for this document ],
        expiry: "2009-05-08"  
     }
   }
  ]
]

List documents in a given folder

By default the listDocuments call returns all documents in all folders. To list the documents in a given folder, you can set the 'p' parameter to the parent folder ID, e.g. p=2009-01-01/abc123 in the call to listDocuments.php. This will restrict the results to just those documents with the given folder as their immediate parent; note that to list subfolders you would need to do an extra call for each subfolder. You can set p=top to list just the documents in the top level folder, and leave the setting empty: p= to list all documents in all folders. You can get a list of folder ids, names and the folder hierarchy using the listFolders call described below.

// return info on all documents in all folders (the default):
  listDocuments.php? ... &p=

// documents with given folder as their immediate parent:
listDocuments.php? ... &p=2009-01-01/abc123

// documents in the top level folder:
listDocuments.php? ... &p=top

Fetch lists of documents and their notes

To fetch the notes for all documents uploaded in a given time frame, set withnotes=1 in the call to listDocuments.php described above in section 3. For each document returned which has notes, you will get an extra field "notes" containing an array of notes. For large numbers of documents, this API request will be slower than fetching the basic information, so for scalability you may wish to restrict requests to a few months at a time.

[ // array of months
  [ // array of doc meta for a month
    {  // sample extended metadata for a document:
      name: "10.1371_journal.ppat.0030096-S.pdf",
      code: "zvq123",
      date: "2008-05-08",
      owner: "joe@example.com",
      meta: {
        // ... meta for doc as before
      }
      notes: [ // array of notes in creation order
        {
          pageurl: "local:2008-05-08/zvq123", 
          type: "note",                   // or "reply"
          pagetitle: "", 
          context: "some sentence about jane bloggs and her collection of newts",
          subject: "jane bloggs",
          notetext: "this is the text of the note itself",
          signed: "joe",                  // public signature for note
          date: "2008-05-07 12:13.12",    // time note written in GMT
          tags: "person, contact",        // tags when first created
          match: "page-1:8:10",           // where note is attached (page 1, from word #8 to word #10)
          gid: 1,                         // ID of this note
          color: 2,                       // index of the background color of note
          state: "live",                  // "dead" for deleted notes
          finalTags : "person, contact",  // latest version of tags (maybe modified by replies)
          replies: []                     // {optional} list of replies to this note
        }
      ]
    } // end of metadata for document
  ] // end of array for month
] // end of array of months

Delete document

The deleteDocument.php call removes a document. If the given user is not the owner of the document it will just remove the document from their list. Arguments can be either GET or POST:

deleteDocument.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 selected user
    &api-auth=xyz1234543983jeflgnwefgdgd   # The signed hash code.    

    &d=2008-01-02                          # The document upload date
    &c=abc123                              # the document code

The return value is either "OK", or "ERR {message}".

Add a note to a document

The addNote.php call lets you add a note to a particular phrase of a document programmatically. It is also used for posting note edits, replies and deletions.

http://yoursite.com/annotate/php/addNote.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 annotate user
    &api-auth=xyz1234543983jeflgnwefgdgd   # The signed hash code.    

    &d=2008-01-02                          # The document upload date
    &c=abc123                              # the document code

HTTP POST parameters:
  notetext              # e.g. 'this is a note'
  tags                  # e.g. 'person, important'
  subject               # the highlighted phrase
  context               # the sentence the note came from
  type                  # 'note' or 'reply'
  match                 # e.g. page-1:10:13  is a note on page 1 from word 10-13
  state                 # 'live' or 'dead'
  gid                   # leave empty for new note; set for edits / replies
  signed                # leave empty for default; can override user signature here
  replyid               # only needed for editing / deleting existing replies

  linkTo                # (optional) target URL if this is a note about a link
  linkTitle             # (optional) target URL title if this is a note about a link
  drawing               # (optional) the drawing commands for freehand 
                        #  annotations as a json array

The return value is "OK {note number}" or "ERR {error message}".

You might find it useful to try creating some notes using the normal annotate gui, and fetching the list of notes using the calls in the List notes section below which also includes a more detailed explanation of the note parameters.

To edit a note, simply call addNote.php and set the gid field to be the same as the note you are editing. To reply to a note, again set the gid of the note, and set the type field to 'reply'. To delete a note, set the gid of the note and the state field to 'dead'.

To edit/delete a reply to a note, you need to know its replyid; this is the note number of the reply when first added, and is also set on loading the notes in the 'replyid' field. For new replies, leave the replyid parameter empty.

List notes on a document

The listNotes.php call will fetch the list of notes for a single document, as viewed by the given api-annotateuser, along with the document level metadata, e.g. for a document with date "2008-05-08" and code "zvq123", you can do a HTTP GET call like:

http://yoursite.com/annotate/php/listNotes.php?    
     api-user=joe@example.com
     &api-requesttime=1234566
     &api-annotateuser=jill@example.com
     &api-auth=ABC123
     &d=2008-05-08                # The document upload date
     &c=zvq123                    # The document code

     &from=2010-01-01             # (optional) YYYY-MM-DD
     &to=2020-01-01               # (optional) YYYY-MM-DD

     &withemails=1                # (optional)
     &allnotes=1                  # (optional)

The return value is a JSON encoded object with fields meta and notes. Note that different api-annotateusers may see a different set of notes if some are marked 'private' (for author only) or 'feedback' (for author and document owner).

From v. 4.3 "withemails" flag (if set to 1) returns an additional field in the JSON object "toemail" which is the "to" field translated into an array of user emails (when not set to _viewers or _self).

From v. 4.3.5 "allnotes" flag (if set to 1) returns all notes on the server (including private notes) when api-annotate user is equal to api-user.

{
     meta : {     
        created: "2008-05-08 13:09.19",
        title: "A paper on XYZ",
        notes: "These are some notes about the whole document...",
        tags: "paper, pdf, important",
        code: "zvq123",
        date: "2008-05-08",
        // ... other document level metadata fields as above
     },
     notes : [    
        {
          pageurl: "local:2008-05-08/zvq123", 
          type: "note",               
          pagetitle: "", 
          context: "some sentence about jane bloggs and her collection of newts",
          subject: "jane bloggs",
          notetext: "this is the text of the note itself",
          author: "joe@example.com",      // userid of the note author (an email)
          signed: "joe",                  // public signature for note
          date: "2008-05-07 12:13.12",    // time note written in GMT
          tags: "person, contact",        // tags when first created
          match: "page-1:8:10",           // where note is attached (page 1, from word #8 to word #10)
          num: 1,                         // num of this note
          gid: 1,                         // ID of this note
          color: 2,                       // index of the background color of note
          mark: "h",                      // "h" - normal text highlight, "s" - strikethrough, "i" - insert, "l" - link
          state: "live",                  // "dead" for deleted notes
          finalTags : "person, contact",  // latest version of tags (maybe modified by replies)
          replies: []                     // {optional} list of replies to this note
          toemail: []joe@example.com,..]  // {optional} list of addressees as email addresses
       }       
       //  , { ... fields of 2nd note ... }
     ]
  }

The note fields in detail

The notetext field contains the text of the note; the tags contains the comma separated tags. the subject is the highlighted text; the context contains a few words either side of the highlighted text. Each note also has a gid which is unique for a particular document. Different edits of a note will have the same gid but unique num values. The signed field is the signature of the user who made the note, the author field is their full userid (an email). The date field has the time stamp (in GMT). The color field is an index into the color chooser in the GUI. The mark field stored the type of the highlight mark on the text - 'h' for normal highlight, 's' for strikethrough, 'i' for an insert mark, 'l' for an inline hyperlink (see below). Replies to a note are stored in similar note objects, with the gid field set to the id of the note they are replying to.

  1. Inline hyperlinks

    It is possible to set the linkTo URL field and the mark to 'l' for inline hyperlinks. These are displayed with a blue underline.

  2. Freehand drawings

    For freehand notes made using a tablet pen device, there is a drawing field which contains the vector drawing instructions; see section 4.5 below for details.

Attachment of notes to page text

The match field of a note determines where in the page it will be attached. For PDF documents, the coding for highlighted text is:
match : "page-1:8:10" indicating that this note is attached to page 1 from word index #8 to #10 inclusive. The Word indices are based on the array of words extracted from the PDF page. You can access the list of words for page 1 of a PDF document uploaded on "2008-01-15" with code "ABC123" using a HTTP GET on listWords.php (note that you do not need to sign this request as it includes the document code):

http://yoursite.com/annotate/php/listWords.php?d=2008-01-15&c=ABC123&p=1

The list of words for each page is coded as an array of arrays; each word is an array [word, x1, x2, y1, y2], with the positions in PDF coordinates e.g.:

[
["Enhancing ", 90.708, 162.276, 98.412, 111.362 ],
["documents ", 166.168, 240.844, 98.412, 111.362 ],
["with ", 244.736, 272.736, 98.412, 111.362 ],
["annotations ", 276.628, 355.966, 98.412, 111.362 ],
["and ", 359.858, 384.750, 98.412, 111.362 ],
["machine-readable ", 90.708, 209.750, 115.212, 128.162 ],
["structured ", 213.642, 282.872, 115.212, 128.162 ],
["information ", 286.764, 363.764, 115.212, 128.162 ],
// ...
]

Attachment of notes to images

For notes attached to highlighted rectangles / ovals on the page, the match encoding is as follows:

match: "R1:3:100:200:50:40" refers to a region on page 3, top left coords: (100, 200), 50 wide, 40 high
The units are in PDF coordinates (points).

The match field for regions is ":" separated, and starts with "R1"  (region version 1):
  R1:{page#}:{x}:{y}:{w}:{h}

In addition, the border style is set with the "border" field:

border: "B1:#000000:3:0:#ffffff:1:2:1:0"

The border field value is colon separated containing the values:
  "B1" indicates a border definition, version 1
  outer color (RGB hex format)
  outer width in pixels
  outer style (0=solid, 1=dots, 2=dashed)
  inner color (eg the dashed white line above a wider solid black border)
  inner width in pixels
  inner style(0=solid, 1=dots, 2=dashed)
  inner offset (so 1 means there is one pixel of the main border before the inner one starts)
  shape (0= square, 1=oval, 2=dotted oval)

Replies to notes

Replies to a note are included in the 'replies' array, which is an array of note objects with type set to "reply":

notes: [
   {
          pageurl: "local:2008-05-08/zvq123", 
          type: "note",                  
          // ... other fields as above ...
          finalTags : "person, contact, important",  // latest version of tags (may be modified by replies)
          replies: [
             {
                pageurl: "local:2008-05-08/zvq123", 
                type: "reply",
                subject: "(reply)",
                notetext: "this is a reply to the note...",
                signed: "jack",                     // public signature for note
                date: "2008-05-07 14:13.12",        // time note written in GMT
                tags: "person, contact, important", // tags when reply created
                gid: 123,                           // ID of the note this is a reply to
                replyid: 151,                       // ID of this reply
                color: 2,                           // bg color index of this reply
                state: "live"                       // "dead" for deleted notes
             }
             // , { more replies ... }
          ]
    }
    // , { fields of note 2 ... }
  ]

The entries in the replies array are notes with type set to "reply", and the same gid value as the main note. The tags field records the tags as they were updated by the reply, so it is possible to extract the complete tag history if replies add / remove tags to the note. The finalTags field of the note records the most recent tag state of the note. The replyid field of a reply is needed for editing / deleting replies; supply it along with the gid of the original note to addNote.php to update a reply.

Freehand drawing annotations

Freehand annotations are stored in a drawing field, which contains a JSON encoded array; a sample is below:

// a note:
  {
     pageurl: "local:2010-01-01/abc123",
     match: "R1:4:70:500:200:200",  // rectangular region
     drawing: [                     // list of strokes
       {
         color: "#ff0000",            // RGB color, css format
         width: 2,                    // line width, in pts
         np: 42,                      // number of points
         time: 1200,                  // start time of stroke (ms)
         xpts: [10.2,13.3,15.7,10, ... ],   // X offset coords (in pts)
         ypts: [10.4,10,12,15, ... ],   // Y offset coords (in pts)
         times: [0,3,14,40,80, ...],  // timestamps (ms)
         {pressure: [30,40,45,45,20, ...]}  // (optional) pen pressure at each point (1-100)
       }, 
       {
         color: "#0000ff",
         // ... rest of fields for stroke 2
       },
       // {... more strokes}
     ]
  }

The drawing field, if present, encodes a freehand drawing as a list of pen strokes. The match field includes the highlighted rectangle within which the drawing had been done; the format of this is the same as for rectangle annotations, i.e. "R1:{page}:{x}:{y}:{w}:{h}". The drawing points xpts and ypts are relative to this rectangle; all coordinates are in PDF points (1/72 inch). If the drawing has been done on a pressure-sensitive graphics tablet, there will also be an array of pressure information - which could be displayed as opacity or line thickness in your application.

Copy notes to a duplicate

The apiCopyNotes.php call copies notes from one document to a duplicate copy. It can be useful if you gather internal comments on one copy, then want to make a tidied up version for an external client. You supply dates and codes for original and duplicate, and can replace the note ownership (e.g. if you want to make all notes editable by a given user before sending to the client).

http://yoursite.com/annotate/php/apiCopyNotes.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 admin user too.
    &api-auth=xyz1234543983jeflgnwefgdgd   # The signed hash code.  


    &d1=2011-01-01&c1=abc123          # Date and code of orig doc
    &d2=2011-01-01&c2=xyz456          # Date and code of target doc
    &newauthor=jack@example.com            # {optional} set the author of all copied notes
    &newsig=jack                           # {optional} set the signed field of all copied notes

The return value is OK + msg or ERR + msg.

Delete all document's notes

The apiDeleteNotes.php call lets you wipe all notes on a document permanently. If you just want to delete an individual note, see the addNote call above (and append a note with a given ID and state='dead').

http://yoursite.com/annotate/php/apiDeleteNotes.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 annotate user
    &api-auth=xyz1234543983jeflgnwefgdgd   # The signed hash code.    

    &d=2008-01-02                          # The document upload date
    &c=abc123                              # the document code

    &bak=1                                 # (optional) backup old notes

    &leavelinks=1                          # (optional) don't delete links

The return value is "OK" or "ERR {error message}". If you set bak=1 it will take a backup copy of the old notes on the server.