HTTP API
Your apps can make HTTP requests to Papertrail to programmatically search for events and manage groups, saved searches, and systems.
Usage
The REST API is entirely optional and not necessary for typical use of Papertrail. Example uses:
- search or tail logs for post-processing (using the same API as papertrail-cli) (also see webhooks)
- create a saved search, like for a string provided by a user of your app (also see linking to searches)
- obtain settings for a given system, like for automated configuration (also see Configuration)
- create groups or update group membership (also see group wildcards)
Overview
Authentication
All API requests are authenticated using either:
- An API token in the
X-Papertrail-TokenHTTP header (recommended). Find your token in Profile - HTTP Basic Authentication with a papertrailapp.com username and password
URL
All Papertrail API requests are rooted at
https://papertrailapp.com/api/v1/.
Example URL: https://papertrailapp.com/api/v1/systems.json.
Examples
These 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
Authenticate with an API token and search events for
Critical error as a quoted phrase:
curl -v -H "X-Papertrail-Token: abc123" "https://papertrailapp.com/api/v1/events/search.json?q='Critical error'"
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
Format

Either:
- Append
.jsonto the request path, such as:/api/v1/systems.jsonor/api/v1/groups/42.json - Include
format=jsonin query parameters
Responses containing multiple items are arrays. Responses about a single item are hashes. No root node is present.
Requests and Responses
Request data uses URL-encoded query parameters. Attributes are typically part of a hash named after the item type, such as:
system[name]=New%20System&system[ip_address]=1.2.3.4
See curl examples above or response examples below.
Update requests may contain all attributes or only the attribute(s) which are to be modified. Absent attributes will be left unmodified.
Errors
Failed requests return 400 Bad Request.
Authentication failures return 403 Unauthorized.
For failed requests, a JSON hash is returned containing a single
key called message. For example:
{"message":"Sad panda"}
Hypermedia
API responses include URLs for obtaining details about, or performing actions on, related items. For example, a client can query for all systems, then follow URLs in the API responses to:
- obtain detail about a specific system, then
- obtain details about a specific group it is a member of, then
- perform an event search for that group
As a result, an API consumer will often only need to hardcode one URL.
Hypermedia links are contained in a hash key called
_links with a hash per relation. For example:
"name":"Production servers",
"_links":{
"self":{
"href":"http://.."
},
"html":{
"href":"http://.."
}
}
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.search: API URL to search for events from or about this item (where applicable).
API Endpoints
Within https://papertrailapp.com/api/v1/:
| Item | Operation | Verb | Path | Path Example | Required |
|---|---|---|---|---|---|
| Events | Search | GET |
events/search |
events/search.json |
|
| Item | Operation | Verb | Path | Path Example | Required |
| Systems | List | GET |
systems |
systems.json |
|
| System | Show | GET |
systems/<id> |
systems/42.json |
|
| System | Register | POST |
systems |
systems.json |
name, ip_address |
| System | Update | PUT |
systems/<id> |
systems/42.json |
|
| System | Unregister | POST |
systems/<id> |
systems/42.json |
|
| System | Join Group | POST |
systems/<id>/join |
systems/42/join.json |
group_id |
| System | Leave Group | POST |
systems/<id>/leave |
systems/42/leave.json |
group_id |
| Item | Operation | Verb | Path | Path Example | Required |
| Saved Searches | List | GET |
searches |
searches.json |
|
| Saved Search | Show | GET |
searches/<id> |
searches/42.json |
|
| Saved Search | Create | POST |
searches |
searches.json |
name, query |
| Saved Search | Update | PUT |
searches/<id> |
searches/42.json |
|
| Saved Search | Delete | DELETE |
searches/<id> |
searches/42.json |
|
| Item | Operation | Verb | Path | Path Example | Required |
| Groups | List | GET |
groups |
groups.json |
|
| Group | Show | GET |
groups/<id> |
groups/42.json |
|
| Group | Create | POST |
groups |
groups.json |
name |
| Group | Update | PUT |
groups/<id> |
groups/42.json |
|
| Group | Delete | DELETE |
groups/<id> |
groups/42.json |
Examples: Provisioning API
Systems
Papertrail automatically recognizes most systems so that explicit configuration is not needed. See Add Systems. The REST API handles unusual cases like:
- automatically registering lots of systems which need explicit configuration (hosting company)
- changing settings on many systems (synchronizing with an existing system metadata source)
- identifying systems which have stopped sending logs
In the examples below, whitespace is added for clarity.
List
[
{
"name":"www5",
"id":3248,
"ip_address":"1.2.3.4",
"hostname":null,
"last_event_at":null,
"syslog": {
"hostname":"logs.papertrailapp.com",
"port":514
},
"_links": {
"self": {
"href":"https://papertrailapp.com/api/v1/systems/www5.json"
},
"search": {
"href":"https://papertrailapp.com/api/v1/events/search.json?system_id=3248"
},
"html": {
"href":"https://papertrailapp.com/systems/www5"
}
},
},
{
# Another system
}
]
Notes:
last_event_atmay be a timestamp or null.hostnamemay be a string or null.
Show
See List. Only the hash for the requested system is returned.
Register
- Required:
name,ip_address - Optional:
hostname(filter events to only those from this syslog hostname)
system[name]=My%20Big%20Server&ip_address=2.3.4.5&hostname=bigserver
Update
See Register.
Groups
List
[
{
"name":"All Systems",
"id":31,
"system_wildcard":"*",
"systems":[
# see "Systems - List" for example array
],
"_links": {
"self": {
"href":"https://papertrailapp.com/api/v1/groups/31.json"
},
"search": {
"href":"https://papertrailapp.com/api/v1/events/search.json?group_id=31"
},
"html": {
"href":"https://papertrailapp.com/groups/31"
},
},
},
{
# Another group
}
]
Notes:
- All systems (whether static members or matching via wildcard)
will be included in
systems. system_wildcardmay be a string or null.
Show
See Create. Only the hash for the requested group is returned.
Create
- Reqired:
name - Optional:
system_wildcard,system_ids
group[name]=us-west%20zone&group[system_wildcard]=*west*&group[system_ids][]=31&group[system_ids][]=62
Update
See Create.
Saved Searches
List
[
{
"name":"Login rejections",
"id":1,
"query":"\"access denied\" OR ssh",
"group": {
"name":"All Systems",
"id":31,
"_links": {
"self": {
"href":"https://staging.papertrailapp.com/api/v1/groups/31.json"
}
}
},
"_links": {
"self": {
"href":"https://staging.papertrailapp.com/searches/1.json"},
"search": {
"href":"https://staging.papertrailapp.com/api/v1/events/search.json?q=%22access+denied%22+OR+ssh"},
"html": {
"href":"https://staging.papertrailapp.com/searches/1/edit"
}
}
}
]
Show
See List. Only the hash for the requested search is returned.
Create
- Required:
name,query - Optional:
group_id(default: All Systems or first group)
Search API
The most basic example is simply to hit the event search API
endpoint,
https://papertrailapp.com/api/v1/events/search.json.
Try
it.
You'll receive the most recent 100 log events. You may be prompted to re-authenticate even when already logged in to the papertrailapp.com Web site.
Constrain Query
To limit results to only a specific group or system, include
system_id or group_id in the query
string. For example:
search.json?system_id=1234
search.json?group_id=2345
Also, system names which contain only numbers, letters, and
underscores (like hostnames) can be used as arguments for
system_id, in lieu of the Papertrail ID. The attribute
is the Papertrail system name (name in the system JSON
hash).
This can simplify linking to results for a single system, since no name-to-mapping API query is necessary. For example:
search.json?system_id=www42
search.json?system_id=my-big-server
See below for how to perform a search.
Example
Here's a live example and code from the
papertrail-cli gem. Install it or
read
search_query.rb source.
Response
Papertrail responds with a JSON hash containing 3 important keys:
events: an array of hashes of log events (one hash per event)min_id: the smallest event ID presentedmax_id: the highest event ID presented
The following hash keys are defined for each log event:
idreceived_atgenerated_atsource_namesource_ipfacilityseverityprogrammessage
A response containing no matching events will return an empty
events array, such as:
{"max_id":"0","reached_beginning":true,"events":[],"min_id":"0"}
Search
To search for a specific message or string, add the optional
parameter q (as in query). All search queries that
work in the Papertrail Web interface should work in the API.
All parameters should be URL-encoded, as is standard for GET query strings. For example, the search string:
bob OR ("some phrase" AND sally)
would be this URL-encoded GET query string:
q=bob%20OR%20(%22some%20phrase%22%20AND%20sally)
Tail
Apps may implement a "live tail" (tail -f) style
display by performing multiple successive searches for the same
search query (or no search query). To do this, the
max_id value from the prior result set must be passed
back to the Papertrail API as the min_id
parameter.
When your search query changes, omit the min_id
from the prior search's result set.
Older Events
By Event ID
To obtain older events (rather than current events or tailing
current events), a max_id may be passed to Papertrail.
This is the newest (highest) ID that your app would like to see,
and Papertrail will return the newest events that are older than
that ID.
To scroll back through older events, like for a
progressively-older tail, the min_id from a Papertrail
response would be passed back in as the max_id. You'll
receive events older than that response.
By Time
If you have a timestamp but not an event ID, pass
max_time or min_time with your first
request (rather than max_id or min_id).
These should be in Unix time, GMT.
After the first request/response, if successive queries are
needed, provide max_id as in "By Event ID" above.
Example response
Here is a response with 2 log events:
{
"max_id":"7711582041804800",
"min_id":"7711561783320576",
"events":[
{"hostname":"abc","received_at":"2011-05-18T20:30:02-07:00","severity":"Info","facility":"Cron","source_id":2,"message":"message body","program":"CROND","source_ip":"208.75.57.121","display_received_at":"May 18 20:30:02","id":7711561783320576,"source_name":"abc"},
{"hostname":"def","received_at":"2011-05-18T20:30:02-07:00","severity":"Info","facility":"Cron","source_id":19,"message":"A short event","program":"CROND","source_ip":"208.75.57.120","display_received_at":"May 18 20:30:02","id":7711562567655424,"source_name":"server1"}
]
}
Papertrail uses 64-bit event IDs, which Javascript has trouble
with, so the id value is a string. The other values
are consistently set to the type you would expect. No values should
be null except for program (when none is defined by
the message). An empty message body is a blank string ('').