SethH

API Updated

28 posts in this topic

A new version of our API, 1.20, is now available. You can download the updated SDK from the usual location, http://www.evernote..../developer/api/. There are several exciting changes in this update:

Read-only notes

You may have noticed that notes created by Evernote Food and Evernote Hello are read-only when viewed in other Evernote clients. We added this functionality so that we could store user-visible structured data within the body of a note without the risk of the user damaging the structure by editing the note in one of our WYSIWYG note editors. Future versions of our desktop apps will support the Hello and Food note types and will allow editing of these notes.

A note is marked as read-only by setting the new Note.attributes.contentClass field. Applications that encounter a note with a non-empty contentClass MUST treat the note as read-only unless they explicitly support the specified content class. Since we haven't published the Hello and Food content specs yet, all of your applications should treat these notes as read-only.

The contentClass field indicates the type of content contained in the note body. Note bodies must still be valid ENML; think of contentClass as a profile of ENML, requiring that the ENML content follow a specific structure. The contentClass for Food notes is evernote.food.meal, while Hello uses evernote.hello.profile and evernote.hello.encounter. Third-party applications can create their own contentClass using the format companyName.appName[.noteType]. We encourage you to think hard before using the contentClass, since the user loses some functionality when a note is not editable in an Evernote client application. If you're considering using contentClass, we'd love to chat with you about how you plan to use it.

You can search for notes with a specific contentClass by including contentClass:string in your search term (the NoteFilter.words field) when you call findNotes. You can include a trailing wildcard, e.g. contentClass:evernote.hello.*.

Application data

At your request, we've added a place for you to store your application-specific metadata. The new Note.attributes.applicationData field contains a map/dictionary in which you can store up to 4kb of non-user-visible metadata used by your application. You MUST use your API consumer key (not the consumer secret, which is suppose to be ... secret) as the map key. If you have multiple applications that will use the same application data but use different API keys, choose one of your keys to use as the map key.

The data that you store in applicationData is completely opaque to us. You can use any format you want to store your metadata: JSON, XML, CSV, whatever you want.

When you fetch a note using getNote, you'll get back a list of the applicationData keys that are set for the note, but for efficiency, we're not returning the actual values. To get your app's applicationData, first fetch your note, then call NoteStore.getNoteApplicationDataEntry with your map key. To set or update your applicationData entry on a note, use NoteStore.setNoteApplicationDataEntry. To remove your app's applicationData entry, use NoteStore.unsetNoteApplicationDataEntry. Don't remove anybody else's entry, and don't call updateNote with an updated Note.attributes.applicationData field that messes with or omits somebody else's existing entries.

You can search for notes that contain a specific applicationData key by including applicationData:keyName in your search term (the NoteFilter.words field) when you call findNotes. You cannot search within applicationData values.

There's also a corresponding Resource.attributes.applicationData field on every Resource, and corresponding get/set/unset functions for resource applicationData.

Place name

The new Note.attributes.placeName field lets a user store a human-readable description of the location for a note. Notes can already store lat/long data; this field is meant to provide a more meaningful description such as "home", "work" or the name of a restaurant that an Evernote Food note was created at. DO NOT auto-populate this field! When set, it should contain a value chosen by the user. If the value is simply automatically determined based on geolocation, it's not worth including.

You can search by placeName by including placeName:name in your search term when you call findNotes. As with other parts of our search grammar, you can include a trailing wildcard, so that you can search for "placeName:taco* to find "Taco Bell", "Taco House" and "Tacorama!".

Please let us know how these new fields work for you. We're really excited about the opportunities that contentClass and applicationData provide for third party developers!

2 people like this

Share this post


Link to post

Hi,

I've downloaded new sdk, and tried to build the sample for cocoa in it. I like new features especially the 'Application data'. It stir my imagination for the new apps.

By the way when I run Analyze for the sample in Xcode4.2 some warnings were reported. Some of them are about NoteStore.m and UserStore.m.

I frequently check my code using Analyze so they are little annoying even if they do no harm.

I would be happy if you could fix them.

Thank you and happy holidays!

Share this post


Link to post

These look like very cool additions. Can you clarify one aspect of the ApplicationData field, though...

You say:

>> and don't call updateNote with an updated Note.attributes.applicationData field that messes with or omits somebody else's existing entries <<

Since according to the docs, UpdateNote requires supplying the FullMap parameter, it sounds like you're saying that all calls to UpdateNote must include all existing ApplicationData keys and values that exist in that note whether your app set them or they belong to another app. But it seems unlikely to me that's what is really required - that would be a lot of extra work for me to have to read and then re-send everyone else's info. So can you say some more about this? Thanks!

Share this post


Link to post

If you're not changing any NoteAttributes, simply omit Note.attributes (leave it unset) when you call updateNote.

If you're changing some NoteAttributes, but not anything in Note.attributes.applicationData, simply omit Note.attributes.applicationData (leave it unset) when you call updateNote. Alternately, if you get a note via getNote and Note.attributes.applicationData.keysOnly is set, leave it as-is when calling updateNote and no changes will be made to the applicationData.

Where in the docs does it say that you need to include the fullMap?

Share this post


Link to post

Thanks, I'll update that. It should say something like "when a client wants the server to update the contents of a LazyMap"...

Share this post


Link to post

Is there a planning for SDK update to follow the API update ? I'm eager to use the new features with the PHP SDK. For now, I've been trying to add Note.attributes.contentClass support myself to the PHP SDK, but with no luck.

Share this post


Link to post

You must download the latest version of the SDK and it will work fine. We updated the SDK when we announced these changes.

Share this post


Link to post

A new version of our API, 1.20, is now available. You can download the updated SDK from the usual location, http://www.evernote..../developer/api/. There are several exciting changes in this update:

Application data

You can search for notes that contain a specific applicationData key by including applicationData:keyName in your search term (the NoteFilter.words field) when you call findNotes. You cannot search within applicationData values.

Please let us know how these new fields work for you. We're really excited about the opportunities that contentClass and applicationData provide for third party developers!

Seth, thanks for the new APIs. Very exciting!

I'm particularly interested in the Application Data APIs.

Are the applicationData keys indexed?

Can we expect a search for one or more applicationData keys (key1=<value1>, key2=<value2>, etc) to be as fast as the normal Evernote search for Tags?

Thanks.

Share this post


Link to post

I was about to refer you to the free manual, but I realized that the relevant content was lost in the move to dev.evernote.com. Mea culpa!

You can search for notes that have a given key. The keys are indexed, so the search will be as fast as a search by tag, yes. From the admittedly-long-but-now-updated Search Grammar page:

applicationData:[string] - matches notes that have an entry in the applicationData map with a key that matches the argument. This can allow an application to find all of the notes that it has added application-specific metadata.

Share this post


Link to post

You can search for notes that have a given key. The keys are indexed, so the search will be as fast as a search by tag, yes. From the admittedly-long-but-now-updated Search Grammar page:

applicationData:[string] - matches notes that have an entry in the applicationData map with a key that matches the argument. This can allow an application to find all of the notes that it has added application-specific metadata.

Seth, thanks for this info. It is very helpful. I have studied the reference, but I still have a few questions:

  1. Let's assume I create two applicationData Keys:

    1. Asset_Date
    2. Asset_Type
    3. Can I do a search for Asset_Type = "Furniture" ?
    4. Can I do a search for (Asset_Date >= 01/01/2011) AND (Asset_Date < 01/01/2012)
      • Or, better yet, a search for Year(Asset_Date) = 2011
      • This implies that the Keys can be assigned a data type, like "Date/Time"
      • Can this be done?

Thanks for your help.

Share this post


Link to post

applicationData:[string] - matches notes that have an entry in the applicationData map with a key that matches the argument. This can allow an application to find all of the notes that it has added application-specific metadata. E.g.:
  • applicationData:myapp
    • Matches notes with a “myapp” entry in the applicationData map

    [*]applicationData:*

    • Matches notes that have at least one entry in the applicationData map

Application data is a string. Given that, plus the examples, best bet is that you get to do the usual string matching operations on them, just like, say, tag names, at least with the standard Evernote search grammar. You're only matching on the keys, as best as I can tell. I believe that an application can retrieve values for specific keys if they want, though.

Share this post


Link to post

A given application is only allowed to store one key in the app data map. The string value associated with that key is freeform, so you can build your own dictionary inside of that, with key-value pairs that your application uses. You don't want to go putting individual key-value pairs directly into the map, though. Does that make sense?

Given this, the search is somewhat limited: you can find all maps that your app has added application data to, but you can't search on the actual values you've stored.

Share this post


Link to post

Given this, the search is somewhat limited: you can find all maps that your app has added application data to, but you can't search on the actual values you've stored.

Thanks for the reply.

So, in plain English, there is no way to create and search for user-defined (or app defined) fields (like below), correct?

(Asset_Type = "Furniture") AND
(Asset_Date = "20110424")

Share this post


Link to post

There is no way to search for app-defined fields. You can create them, but the Evernote search API doesn't allow you to search them.

Share this post


Link to post
The new Note.attributes.applicationData field contains a map/dictionary in which you can store up to 4kb of non-user-visible metadata used by your application

Is that 4kb per developer (app key), or are we sharing that 4kb with all developers using that field?

-- roschler

Share this post


Link to post

Per app key (developer).

Share this post


Link to post

Is application data accessible through local API?

many thanks

Share this post


Link to post

@milos, the answer to what's accessible depends on the platform.

The local API for Mac is defined by the scripting dictionary of the Mac client which you can inspect at any time using an AppleScript editor.

The Windows client exports an ENEX file in ENML format (don't think there's anything in the file beyond ENML) so you can again check for yourself - export a note and see if there are elements you want.

Looking at the schema linked from the ENML page, it doesn't seem to include this metadata so the answer is probably no.

1 person likes this

Share this post


Link to post

Thanks Andy.

It is a pity though. It would extend the power of local integration with Evernote considerably if the app specific meta data and such can be kept together with the note... As far as I can tell I am unable (on Mac) to create read-only notes either (in order to keep the app specific data bound with the Evernote account at least). There are workarounds, of course, but none that I can think of are very elegant (which is to say, resilient and "safe-to-fail").

Thanks for looking up the schema for me!

Share this post


Link to post

Milos, Andy's correct - the AppleScript dictionary doesn't expose the application data or content class fields.

1 person likes this

Share this post


Link to post

Hi SethH,

Can you please let me know how can we extract the image from resources of a particular note when getbody is empty?

I am getting bodyhash and when I am trying to decode the image in android, it is returning null.


List<Resource> res =note.getResources();
for(Iterator<Resource> iterator= res.iterator(); iterator.hasNext() {
Resource resource = iterator.next();
resource.getData().getBodyHash();
Bitmap bitmap = BitmapFactory.decodeByteArray(resource.getData().getBodyHash(), 0, resource.getData().getBodyHash().length);

}

Thanks

Share this post


Link to post