HTTP API

Papertrail’s HTTP API serves two primary purposes:

  • Manage settings: groups, saved searches, systems, and log destinations. For endpoint details, see Settings API.
  • Programmatic search for events: for endpoint details, see Search API.

Papertrail’s own papertrail-cli exclusively uses API calls documented here. It implements most of the functionality in this document. Install the gem or read its search_query.rb and connection.rb sources.

Papertrail doesn’t accept log messages via HTTP. Why?

API Usage

Example uses

  • Create a saved search for a string provided by a user of your app. See Linking to logs.
  • Get settings for a given system for automated configuration. See Configuration.
  • Create groups or update group membership. See Mapping senders to groups.
  • Invite new members when a new employee joins the team. See Members.
  • Search or tail logs for post-processing (also possible with papertrail-cli). See webhooks to have events pushed to you.

The authentication, format, and request structure is the same for all requests.

Do I need to use the API?

Most common tasks you might want to do outside the UI, like searching for logs, programmatically creating senders or adding them to groups, and retrieving logs during a certain time period, are possible with papertrail-cli, a small command-line tool with simple syntax, so you might be able to skip direct use of the API entirely.

Authentication

All API requests are authenticated using either:

  • An API token in the X-Papertrail-Token HTTP header (recommended). Find the token in your profile.
  • HTTP Basic Authentication with a papertrailapp.com username and password.

Papertrail’s API supports cross-origin resource sharing (CORS), so it’s possible to retrieve log data from another domain. Because session cookies are not used with the API, you may be prompted to re-authenticate even when already logged in to the Papertrail website.

URL structure

The Papertrail API lives at https://papertrailapp.com/api/v1/, with particular endpoints following that prefix.

Example URL: https://papertrailapp.com/api/v1/systems.json.

Format

Requests and Responses

Request data can use URL-encoded query parameters (application/x-www-form-urlencoded), or JSON, for POST or PUT requests. When using JSON, the Content-Type: application/json header is required.

Responses are in JSON. Responses containing multiple items are arrays. Responses containing a single item are objects. No extra whitespace is provided; use a processor or pretty-printer to introduce formatting.

Required values are marked. Any parameters not marked are not required; if their inclusion affects the behavior, or if there is a default value, that is noted.

Update requests may contain all attributes or only the attribute(s) to be modified. Absent attributes will not be modified.

Errors

Authentication failures return 401 Unauthorized.

Failed requests return 400 Bad Request, and a JSON hash is provided containing a single key called message with further information about the issue. For example:

{"message":"Sad panda"}

Methods applied to an endpoint where they are not supported return 405 Method Not Allowed. If the resource is not found, 404 Not Found is returned.

Rate Limits

Papertrail limits the number of API requests made within a period of time.

The API returns the three headers that denote the status of the API rate limits:

  • X-Rate-Limit-Limit - the total number of requests allowed during the rate limit window, currently 25.
  • X-Rate-Limit-Remaining - the number of requests not yet used within the current rate limit window.
  • X-Rate-Limit-Reset - the duration (in seconds) remaining until the rate limit window resets, currently 5 seconds.

When the limit is reached, further requests return 429 Rate Limit Exceeded.

The API limits may be adjusted from time to time. If possible, obey the returned header values rather than hardcoding a specific rate, but please let us know if there’s any mismatch.

API responses include URLs for getting details about, or performing actions on, related items. For example, a client can query for all systems, then follow URLs in the response to:

  • obtain details about a specific system, then
  • obtain details about a specific group it is a member of, then
  • perform an event search for that group.

This allows API clients to avoid hardcoding multiple URLs for different calls.

Links to related resources appear in a hash key called _links with a hash per relation. For example:

{
  "name": "Production servers",
  "_links": {
    "self": {
      "href": "http://.."
    },
    "html": {
      "href": "http://.."
    }
  }
}

When they apply to the item, these relations are used:

  • self: Canonical API URL for item. Consume this for item details.
  • html: Canonical HTML URL for item. Link humans to this resource.
  • search: API URL to search for events from or about this item (where applicable).

Example calls

API examples use curl, a command-line HTTP client.

Authenticate with an API token and list all systems:

$ curl -v -H "X-Papertrail-Token: abc123" https://papertrailapp.com/api/v1/systems.json

Authenticate with an API token and save a search named Important stuff:

$ curl -v -H "X-Papertrail-Token: abc123" -X POST --data 'search[name]=Important+stuff&search[query]=very+important' https://papertrailapp.com/api/v1/searches.json

The same request using JSON:

curl -v -H "X-Papertrail-Token: abc123" -H "Content-Type: application/json" -X POST -d '{"search":{"name":"Important stuff","query":"very important"}}' https://papertrailapp.com/api/v1/searches.json

Be sure to include the quotation marks around keys and values. Most POST requests to the API involve an object (system, group, search, or user) whose specifications are themselves an object (set of keys and values).

Authenticate with a username and password and update the name of group ID 12 to Customer servers:

$ curl -v -u "my@email.com":"s3kr3t" -X PUT --data 'group[name]=Customer+servers' https://papertrailapp.com/api/v1/groups/12.json

Authenticate with a username and password and add system ID 4321 to group ID 12:

$ curl -v -u "my@email.com":"s3kr3t" -X POST --data 'group_id=12' https://papertrailapp.com/api/v1/systems/4321/join.json

The same request using JSON:

$ curl -v -u "my@email.com":"s3kr3t" -H "Content-Type: application/json" -X POST --data '{"group_id":12}' https://papertrailapp.com/api/v1/systems/4321/join.json

In this case, there’s no need for nested objects in the JSON, since there’s no outer object that’s being addressed in the data.

As a final example, a customer has implemented a wrapper library for group and search creation called paper_wrap.

Feel free to contact us and request a code sample for your language, or check out Search API and Settings API for more details.

Submitting log messages

Even though we love HTTP for interacting with logs and settings, Papertrail doesn’t accept log messages over HTTP. HTTP is very poorly suited for realtime logging because its characteristics are almost the opposite of what makes an easy, resilient log sender.

Here’s why HTTP doesn’t do your app any favors:

  • The log submitter (your app) would need to block on a response, which slows down its regular operations. (If it doesn’t block, it needs to queue and/or accept that the messages may be lost, which is arguably worse, not to mention losing many of the benefits of HTTP.)
  • In order to avoid slowing down your app, the log submission usually needs to go in a separate thread, which is non-trivial to implement. For code that’s already running in an event loop, it would introduce complexity and delay to the loop.
  • Scaling logging would mean queueing the log messages in your app and having one or more threads to submit them, or having to deal with backpressure.
  • There’s no standard or even de facto standard.

The final and biggest reason: Sending a syslog packet is extremely easy because at its core, a “syslog packet” is just a simple string (think printf). Generating and transmitting it is usually 2-4 lines of code. It’s often less code and easier to follow than generating an HTTP request (and is much shorter and more elegant than HTTP log submission).

For some more specific ideas, see the Configuration section, or ask us for details.