API documentation

We provide an industry-standard JSON-RPC API that allows you to retrieve and modify your data at any time. Nutshell also provides a minimal HTTP POST API for simple web-to-lead forms.

The data you store in Nutshell belongs to you, and we've designed our open APIs to make it possible for you to work with it however you wish. Please contact us with any questions on using the API.

Endpoint discovery

Nutshell offers a specialized API at api.nutshell.com which your application must use to find the API endpoint for each user.

  • JSON-RPC endpoint: http://api.nutshell.com/v1/json

This API has one method, getApiForUsername. It accepts one parameter, username: the user that wishes to log in.

The API will respond with an array of domains which the user can login to.

"result": {
    "iphone": "app.nutshell.com",
    "api": "app.nutshell.com",
    "login": "app.nutshell.com"
}

Your application should cache this response for the next 10 - 90 minutes.

Try it out!

Building the Endpoint URL

Once your application has the domain name the user should login to, building the rest of the endpoint URL is simple.

The domain should be prefixed with https:// (the Nutshell API requires HTTPS). After the domain name comes the API version, in the format api/vX. api/v1 is currently the only valid version of the Nutshell API. Finally, /json should be appended to the URL, noting that the protocol is JSON-RPC.

Continuing from the example given above, one might end up with the API endpoint URL https://app.nutshell.com/api/v1/json.

JSON-RPC

The Nutshell API is available via the JSON-RPC protocols. Nearly all modern programming languages have libraries for interfacing with a JSON-RPC API.

Nutshell uses JSON-RPC v2.0 and supports named parameters. An SMD (Service Mapping Description) is available via a GET request to the API endpoint.

Authentication

The Nutshell API uses HTTP Basic authentication. All API calls, except requests for JSON-RPC's SMD file, must include the Authentication header.

The username for authentication is either your company's domain or a specific user's email address (see the Impersonation section, below). The password is always an API key.

The Nutshell API is accessible only via HTTPS to ensure that API keys and other sensitive information remain secure.

Here's an example cURL command that retrieves Lead-1000 from Nutshell's JSON-RPC API:

curl -u <domain or username>:<api token> \
-d '{ "id": "<id>", "method": "getLead", "params": { "leadId": 1000 } }' \
https://app.nutshell.com/api/v1/json

Permissions

Impersonation

Each API key may allow or disallow "impersonation".

If impersonation is allowed for an API key, the API consumer may authenticate using any valid user's email address as the username. Any changes the API consumer makes will be logged as if that user had made the changes directly.

If impersonation is not permitted, the API consumer must authenticate using an email within the company's Nutshell application as the username. Any changes the API consumer makes will be logged using the API key's name (set when the key was created).

Web-only

A web-only API key is used to create basic HTML forms using Nutshell's minimal HTTP POST API. Web-only API keys are created with the expectation that they may become public. They cannot be used for authentication to the JSON-RPC API.

Web-only API keys do not use HTTP Basic authentication, nor is impersonation available. See the HTTP POST API documentation for more information.

HTTP response codes

The Nutshell API will return the HTTP status code 401 (authorization required) if the Authentication header is missing or the username or API key is invalid.

The API will return an HTTP 200 status if the Authentication header is valid or authentication is not required.

HTTP POST API

Nutshell offers an alternative, minimal HTTP POST API for users that need to add entities to Nutshell using a simple form. It is much less powerful than the JSON-RPC API. The POST API can only add contacts, accounts, or leads to Nutshell and cannot retrieve, edit, or delete any data.

Every request sent to the POST API will generate one lead, and potentially one contact and one account.

Create a new API key (from the Setup tab, click "API") with Form submissions + Wufoo permission. Note that this API key has no privileges for the JSON-RPC APIs. You will receive a URL that accepts POSTs with the potential field names below. The only mandatory field is at least one subfield for either an account or contact, and the successUrl key.

This API is intended for clients hosting a simple form on a static server with no capability for a more powerful JSON-RPC. As such, the only possible response to a POST API request is a HTTP 301 redirect to the successUrl provided in your form.

If provided, source, product, competitor, and industry names must exactly match the name of an entity already present in Nutshell. Contacts, accounts, and leads are the only new entities that will be created from HTTP POSTs.

If invalid data is received in this request, it is saved as a note on the lead for manual review.

After a lead arrives in Nutshell via the POST API, it is subject to standard process and user assignment, as defined in Lead Distribution. Submissions with the isPending parameter set to a true value will be created in a pending state.

Available Fields

The following fields are available for use in the HTTP POST API:


account[name]
account[industryName]
account[email]
account[phone]
account[url]
account[tags]
account[address][address1]
account[address][address2]
account[address][address3]
account[address][city]
account[address][state]
account[address][postalcode]
account[address][country]

contact[name] contact[title] (requires an account to be submitted simultaneously) contact[email] contact[phone] contact[url] contact[tags] contact[address][address1] contact[address][address2] contact[address][address3] contact[address][city] contact[address][state] contact[address][postalcode] contact[address][country]

source[name]

product[name] product[quantity]

competitor[name]

confidence note isPending tags

successUrl

The tags, contact[tags], and account[tags] fields should consist of a comma-seperated list of tag names, e.g. "tag #1,tag #2".

Custom fields

The POST API will also populate custom fields, if the fields are named the same.

Custom fields are available for leads, contacts, and accounts. Given a custom field called "flavor" in each of those fields, the syntax is


contact[flavor]
account[flavor]
flavor

The latter entry will go into the leads field named "flavor".

Sample form

This form will create a new lead, with an account (using information from Company name & Company email fields) and contact (using the Your name field). If the submitter doesn't include their name, no contact will be created. If the comments box is filled out, it will be attached to the lead as a note.

In this example, a product and source will be attached to the new lead. Note that the product and source must have been created in advance. A favorite flavor will be given to the contact; note that the custom field must have been created in advance.


<form action="https://app.nutshell.com/YOUR_URL_HERE" method="post">

<!-- these URLs are where the submitter will be redirected upon completion -->
<input name="successUrl" value="http://EXAMPLE.COM/thanks.html" type="hidden">

Company name: 
<input name="account[name]" type="text"> <br>

Company email: 
<input name="account[email]" type="text"> <br>

Your name:
<input name="contact[name]" type="text"> <br>

<!-- This custom lead field must already exist in Nutshell -->
Your favorite flavor:
<!-- <input name="contact[flavor]" type="text"> <br> -->

<textarea name="note" placeholder="Comments"></textarea>

<input name="ok" value="Submit" type="submit">

<!-- This product must already exist in Nutshell -->
<!-- <input name="product[name]" value="Widget" type="hidden">  uncomment when you've configured this product -->

<!-- This source must already exist in Nutshell -->
<!-- <input name="source[name]" value="Web form" type="hidden"> uncomment when you've configured this source -->

</form>

Rate limits

We make every effort to make your data as accessible as possible. To maintain a high quality of service, we rate limit a few large requests. Most notably, find (e.g. findLeads()) requests with non-stub responses (stubResponses = true). To a lesser extent, excessive get requests (e.g. getContact()) are also rate-limited.

The degree of rate-limiting may change dependent on current conditions. We do not rate-limit any incoming add or edit requests. Contact us if you have any questions about API usage.

Entities and relationships

At its core, Nutshell tracks objects such as contacts and accounts (known in the Nutshell world as "entities") and the relationships ("maps") between these entities.

Entities returned by the API contain an entityType field which tells API consumers about the entity. (Examples of entityTypes include Users, Teams, Accounts, Contacts.)

Note on Contacts/People and Accounts/Companies: you might notice that Nutshell refers to People and Companies, but the API uses the terminology Contacts and Accounts. Nutshell has made a change to the way we refer to those two top-level entity types, but the API is still configured to use the previous "nouns" Contacts and Accounts. You can read more about this change on our blog, or in our support documentation.

To show related entities, the API embeds stubs of these relationships in API responses. For example, a lead returned by the API has an array called contacts which includes a stub for each contact related to the Lead.

Stubs

For certain API calls, it does not make sense (for performance or bandwidth reasons) for Nutshell to return a full entity complete with all its details. In these cases, the Nutshell API returns "stub" responses.

A stub includes only the most important information about an entity. A stub is indicated by the property "stub": true on the entity.

Stubs use fewer server resources and consume less bandwidth - especially important if your API consumer is a mobile device.

This is a stub for a hypothetical lead:


{
    "stub":               true,
    "id":                 145,
    "entityType":         "Leads",
    "rev":                "5",
    "name":               "Lead–145",
    "status":             10,
    "completion":         100,
    "value": {
        "currency":       "USD",
        "amount":         1780
    },
    "primaryAccountName": "Auto-Owners Insurance",
    "dueTime":            "2010-07-18T12:00:00+0000",
    "closedTime":         "2010-07-18T12:00:00+0000"
}

Stubs are typically returned when an entity is embedded inside another for an API response (for example, an account or contact included in a lead) and optionally for some find* and search* API methods.

Entity types

Use the entityType key on a given API response object to determine its type. Entity types returned by the API are strings, and they are English plural nouns. This is an incomplete list of entityTypes returned by the API, with links to documentation on their structure.

Notes do not currently return their entityType. They may appear in the notes array for Accounts, Contacts, and Leads; and a single note may appear in the logNote key for an Activity.

Relationships

Leads are the single entity type in Nutshell which has the most relationships. Each Lead can be associated with multiple Processes, Sources, Competitors, Products, Contacts, Accounts, and Notes.

Each Lead also includes exactly one:

  • creator (a User)
  • primaryAccount (an Account)
  • milestone (a Milestone)
  • market (a Market)
  • assignee (a User or Team)

Activities have a few relationships. They include one Activity_Type and may include one User (if the Activity has been logged; in the loggedBy key). Activities also have a one-to-many relationship with their participants. Participants may be Users or Contacts.

Accounts and Contacts have a two-way one-to-many relationship. Each Account may be related to multiple Contacts; similarly, each Contact may be related to multiple Accounts. Each Account knows about its Contacts and vice-versa. Because of this two-way awareness, Account-Contact relationships may be modified, added, or removed using both the editContact and editAccount API methods.

Previously Accounts and Contacts mapped to a Lead contained a relationship field consisting of an optional text description of the relationship. In October 2012 this field was removed and is replaced with a single description field on the Account or Contact directly.

Retrieving and editing entities

Retrieving an Entity

To retrieve an entity from the API, use one of the get* methods listed in the API method index. These methods take an entity ID and (optionally) a rev identifier. (See the Revs and ETags documentation for additional information about revs and caching.)

Expected Response

The response for any get* method is typically a dictionary representation of the requested entity. For a detailed description of exactly which fields may be returned for each entity, see the corresponding documentation from the API response index.

For example, the array returned by getLead is documented in Lead.

If an entity is not returned, the response will be an error message or a notice that your currently cached entity is still valid.

Editing an Entity

To edit an entity, use one of the edit* methods listed in the API method index. These methods take an entity ID, a rev identifier, and an array containing new/updated values for the entity.

The rev identifier is mandatory for the edit* methods. See "Revs", below, for an overview of how revs are used in editing an entity.

Expected Responses

The response for any edit* method is typically a dictionary representation of the updated entity. (See "Expected Responses" for retrieving an entity, above.)

If an entity is not returned, the response will be an error message or a notice that you cannot edit the entity because your currently cached entity is invalid. (See "Revs", below, for an overview of how revs are used in editing an entity.)

Multi-Value Fields

Many entities have fields which can contain more than one value. For example, a Contact may have multiple addresses and phone numbers; and a Lead may have multiple Contacts.

Each of these fields, if present in a response, will include one value called --primary. This will be a duplicate of another value in the multi-value field; it represents the primary value (for example, a Contact's primary phone number).

Editing Multi-Value Fields

When you wish to add a value (for example, an additional phone number) to one of these multi-value fields, you must also include all preexisting values in that field. The edit* methods replace all existing values with whatever value(s) you supply in your API call.

This behavior allows you to delete values from multi-value fields using the edit* family of methods.

If a multi-value field is not included in the "changes" array you pass to the edit method, the preexisting values are not affected.

This behavior does not apply to fields that can only contain a single value (such as a Contact's name).

Custom Fields

Certain entity types (currently Leads, Accounts, and Contacts) support custom fields, which can be viewed and edited just like regular fields. In order to prevent name collisions with built-in fields, custom fields are contained within a dictionary with the key customFields.

Custom fields are rendered just like regular fields of the same type. Here's an example response for a getLead request on a lead with a currency custom field named "Budget" and a text custom field named "Reference ID":


"result": {
    "id": 1653,
    "entityType": "Leads",
    ...
    "customFields": {
        "Reference ID": "999-99-9999",
        "Budget": {
            "currency": "USD",
            "amount": "200"
        }
    },
    ...
}

Editing Custom Fields

Editing custom fields can be done by including a customFields dictionary in the changes array you pass to the edit* method. To update or add a custom field, add an entry to customFields with the key set to the custom field's name and the value to the desired value. To delete a custom field value, do the same, but set the value to null.

Here's an example JSON-RPC request that will remove the value for the "Reference ID" field and change the value for the "Budget" field to €40.50 for the above lead:


{
    "jsonrpc": "2.0",
    "method": "editLead",
    "params": {
       "leadId": "1653",
       "rev": "9",
       "lead": {
          "customFields": {
             "Budget": {
                "currency": "EUR",
                "amount": "40.50"
             },
             "Reference ID": null
          }
       }
    },
    "id": "a"
}

Revs

Revs are Nutshell's approach to application-level cache control. The Nutshell API issues a revision identifier (rev key) as part of its response each time you retrieve an entity.

When you call an edit* method, you must include the rev you have cached for the entity you intend to edit. If the entity has been changed on the server since you last retrieved it, the API will not let you make your changes. This prevents the possibility of accidental data loss.

For additional information on revs, see the Revs and ETags documentation.

Finding and searching

The Nutshell API offers many find and search methods which your application can use to retrieve data.

Find vs. Search

The find* methods are used to query the Nutshell database for a set of results.

Some find methods (e.g., findAccountTypes) do not take query parameters; they simply return all possible entities according to the sorting and pagination options you specify. Other find methods (e.g., findAccounts) accept a query parameter. Each find method accepts a specific set of query keys; this is documented in detail in the API documentation for each method.

Some find methods can optionally retrieve stub entities for faster responses, but by default all find methods return full entities.

The search* methods are used to quickly find results matching a given search query string.

These search methods (e.g., searchContactsAndUsers) use the same high-performance search engine that Nutshell uses to power its find-as-you-type feature. The search methods always return stub entities for extremely fast results.

See the entities & relationships documentation for more information on stubs.

Pagination

All find* methods use the same simple interface for pagination. Each method accepts four optional parameters which control pagination: orderBy, orderDirection, limit, and page.

orderBy is the column by which the search results should be sorted. Each find method has its own default (usually name) which is sensible for most queries.

orderDirection may be one of ASC or DESC. Default is ASC.

limit sets the number of results returned per page. Default is 50.

page sets the results page number. Default is 1.

If the page your application retrieves has fewer entities than the limit you sent with the query, you've retrieved the last page of results.

Find and Search Methods

The Nutshell database can be queried with any of these API methods:

  • findAccounts
  • findAccountTypes
  • findActivities
  • findActivityTypes
  • findCompetitors
  • findContacts
  • findDelays
  • findIndustries
  • findLead_Outcomes
  • findLeads
  • findMarkets
  • findMilestones
  • findOrigins
  • findProducts
  • findSettings
  • findSources
  • findTeams
  • findUsers
  • searchAccounts
  • searchCompetitors
  • searchContacts
  • searchContactsAndUsers
  • searchProducts
  • searchSources
  • searchUniversal
  • searchUsersAndTeams

Revs and ETags

The Nutshell API offers solutions for cache validation at the network and application levels.

ETags

Nutshell uses HTTP ETags as a solution for cache validation at the network level. The JSON-RPC API uses ETags as specified in HTTP 1.1, and is useful for simple API optimizations at the network layer.

When a get* or find* method is requested via JSON-RPC with the current ETag in the If-None-Match header, the server will respond with an empty response and a 304 (not-modified) HTTP status. If the document has changed, the response will contain the full requested contented and the new Etag header.

Note that ETags are currently not relevant (and ignored) for edit methods. Use the rev key documented below for version checking.

Revs

Revs are Nutshell's approach to application-level cache control.

The Nutshell API issues a revision identifier (rev key) as part of its response each time you retrieve an entity. Your API client should store this identifier with its cache of the entity.

Note: Revs may appear to be incrementing integers, but your application should treat revs as strings to avoid potential issues in the future.

When you call a potentially-destructive API method (for example, editContact), you must include the rev that you have cached for the entity you are modifying. If that rev doesn't match the rev on the server, the entity has been updated on the server since you last retrieved it. In that case, you won't be allowed to make the change you requested; you'll need to download the latest version of the entity, resolve any conflicts, and retry your edits.

If the entity has been modified since you last downloaded it, you'll get the error "rev key is out-of-date":


"error": {
    "code": 409,
    "message": "rev key is out-of-date",
    "data": NULL
}

When you call a non-destructive API method (for example, getContact) to retrieve an entity you already have cached, you can send the rev that you have for that entity. If the entity hasn't been modified on the server, the API will not return the whole entity again. Instead, it'll include a _notModified attribute in the result:


"result": {
    "entityName": "Contacts",
    "id": 10,
    "rev": "5",
    "_notModified": true
 }

Sometimes, you may want to perform a destructive edit or explicitly ignore Nutshell's revs for some other reason. This is possible, though you should exercise caution when using this functionality. To tell the Nutshell API to ignore revs, pass the string "REV_IGNORE" as the rev of the entity you intend to edit.

Working with files

Several components of the Nutshell API support uploading and downloading files. This document outlines the general workflow.

Where files are available

  • Logged activities may have one or more attachments, representing the audio or video log.
  • Leads can have one or more attached files
  • On-demand ZIP backups can be generated and downloaded

We plan to add additional support for file attachments in the near future.

Retrieving attached files

Logged activities contain a logNote property, an object which may have one or more file objects in its files array. Multiple encodings are created after a file has been uploaded and processed.

Leads have a file property, which contains an array of files associated with this lead, typically uploaded via the web interface.

Sample file object


{
    "entityType": "Files",
    "id": 1234,
    // Where to download this file via HTTPS
    "uri": "https://app.nutshell.com/file/api/1234",
    "name": "activity0logfile_1322783452",
    // An accurate MIME representation of this file
    "mime": "video\/quicktime",
    "rev": "ff6ae801b9584bb37b48d1c6273427a5942385f5",
    // Size of this file in bytes
    "size": 840464,
    // A mime-like internal representation, primarily for our mobile apps
    "clientType": "video\/iphone", 
    // Duration in ms
    "duration": 8327
}

Downloading actual file data

After retrieving the file object documented above, use the object's uri key as the endpoint for the file. You will need to use the same HTTP basic authentication that you use to access the file. Note that these endpoints support HTTP Range: requests, useful when accessing media for HTTP streaming.

Uploading files

Uploading files to Nutshell is a two-part process. First, you will edit the entity, providing the metadata for the file you are about to upload. The response from Nutshell will include a URI resource, to which you should POST the file. The process outlined below is the same for any Nutshell request that allows for uploads. (Currently editLead() and editActivity())

1. Edit a lead to indicate a new file for upload


{
    "method": "editLead",
    "id": "1234",
    "params": {
        "leadId": 24455,
        "rev": "rev",
        "lead": {
            "file": [
                {
                    "entityType": "Files",
                    "name": "myfileto_upload.txt"
                }
            ]
        } 
} }

2. Examine the response to editLead() for the URL to which you should POST


{
    "id": "1234",
    "error": null,
    "result": {
        "entityType": "Leads",
        "id": 24455,
        ...
        "file": [
            {
               "entityType": "Files",
               "id": 5678,
               // this is the URL to post your file
               "uri": "https://app.nutshell.com/file/api/5678",
               "name": "myfileto_upload.txt",
               "mime": "",
               "rev": "",
               "size": 0,
               "clientType": null
            }
        ]
    }
}

3. Post your file to the provided URL

After examining the response for the correct URI to upload your new file, you should create a simple HTTP POST with the contents of your file. This should just be a simple multipart/form-data POST, with file as the key for your file's data. As with downloading a file, you should use your standard HTTP Basic authentication. Here's an example cURL command that uploads test.txt to the file with the URI https://app.nutshell.com/file/api/65: curl -v -u : -F "file=@test.txt;type=text/plain" 'https://app.nutshell.com/file/api/65'

You should be able to immediately download the file from the same URL resource, with an HTTP 200 status, as a way of confirming a successful upload.

Subsequent requests to retrieve the lead will now include the MIME type and size for your newly-uploaded file.

Embedded timelines

If you have a web site or web application where you'd like to embed a Nutshell timeline, you can use our beta iframe-able view.

Search fields

You can choose to embed the entire company feed, or you can embed the timeline from a specific lead, account, or contact. Or, you can search by email address for the appropriate timeline.

Authentication

We don't currently support any separate authentication, so if you're logged into Nutshell, embedded iframes will just use your current credentials.

Examples

Embed your entire company's timeline:

<iframe src="https://app.nutshell.com/timeline" width="600" height="400"></iframe>

Embed a timeline from a specific entity, by adding /timeline to the end of the URL:

<iframe src="https://app.nutshell.com/contact/123-andy-fowler/timeline" width="600" height="400"></iframe>

Embed a timeline for a given email address:

<iframe src="https://app.nutshell.com/timeline?email=customer@example.com" width="600" height="400"></iframe>