Opbeat Intake API

Introduction

Use the Intake API to send information about releases and errors to Opbeat.

Information is sent as JSON objects or form encoded data to an Opbeat HTTPS endpoint. All communication with the Opbeat API happens through SSL.

The HTTP header Content-Type: application/json must be set when sending a JSON object.

Urls

The base url for the Intake API v1 (current) is:

https://intake.opbeat.com/api/v1/

Most resources are releated to an organization and/or an app. Most endpoints follow the patterns of https://intake.opbeat.com/api/v1/organizations/<organization-id>/apps/<app-id>/.

Authentication

POST /api/v1/organizations/<organization-id>/apps/<app-id>/
...
Authorization: Bearer <secret-token>
User-Agent: <client version>
...

Authentication and authorization with the Opbeat Intake API happens by way of bearer tokens. Tokens are available in the Opbeat web interface under App settings.

The User-Agent and Authorization headers are required.

Access tokens must be sent with each request to the Opbeat Intake API. Access token must be specified in the Authorization header.

User-Agent can be an arbitrary string which identifies your client, including its version. For example, the Python client might send User-Agent: opbeat-python/1.0.

Release tracking

Sending a release to Opbeat requires sending two values to https://intake.opbeat.com/api/v1/organizations/<organization-id>/apps/<app-id>/releases/ using HTTP POST. Please note the examples here use form encoded data for the sake of clarity, but JSON should work equally well.

CURL example

$ curl https://intake.opbeat.com/api/v1/organizations/<organization-id>/apps/<app-id>/releases/ \
        -v -H "Authorization: Bearer <secret-token>" \
        -H "Content-Type: application/json" \
        -d rev=d67ccb6502cb89a336bb30a0b6758de9e022b2a2 \
        -d branch=feature/adding-opbeat \
        -d status=completed

Advanved CURL example (per-machine)

$ curl https://intake.opbeat.com/api/v1/organizations/<organization-id>/apps/<app-id>/releases/ \
        -v -H "Authorization: Bearer <secret-token>" \
        -H "Content-Type: application/json" \
        -d rev=d67ccb6502cb89a336bb30a0b6758de9e022b2a2 \
        -d branch=feature/adding-opbeat \
        -d status=machine-completed \
        -d machine=web01.example.com
Attribute Example Description
rev d67ccb6502cb89a336bb30a0b6758de9e022b2a2 Git commit hash of the release
status completed One of completed and machine-completed
branch (optional) feature/new-pretty-avatars Git branch of the deployed release
machine (optional) web01.example.com Denotes the name of the machine where the release was deployed. Only valid with status=machine-completed.

Opbeat will answer with a 404 Not Found if you do not remember to replace organization id, app id and secret token with valid tokens for your app.

Response

The API responds to valid requests with a 202 Accepted.

Example response:

202 Accepted

Error logging

Example request:

$ curl https://intake.opbeat.com/api/v1/organizations/<organization-id>/apps/<app-id>/errors/ \
    -v -H "Authorization: Bearer <secret-token-id>" \
    -H "Content-Type: application/json" \
    --data '{"message": "SyntaxError: Wattttt!"}'

To send log records e.g. exceptions, warning messages etc., you need to send a HTTP POST request to Opbeat. Information pertaining to the log record must be sent as a JSON object to the endpoint.

Please see Authentication section for details regarding authentication.

Building the JSON Packet

Example with exception:

{
    "culprit": "my.module.function_name",
    "timestamp": "1339089430",
    "message": "SyntaxError: Wattttt!",
    "exception": {
        "type": "SyntaxError",
        "value": "Wattttt!",
        "module": "__builtins__"
    }
}

The body of the post is a string representation of a JSON object.

To minimize bandwidth usage, the JSON is preferably gzipped. When sending a gzipped JSON object, the http header Content-Type must be set to application/octet-stream.

Required

The only required attribute is message, but we strongly encourage including as much information as possible.

Optional

There are several optional values, most of which are highly encouraged:

timestamp

{
    "timestamp": "2010-05-08T23:41:54.000Z"
}

Indicates when the logging record was created in the client.

Defaults to the time at which the record was received.

The timestamp should be a ISO 8601 string like: 2010-05-08T23:41:54.000Z. It is also possible to supply seconds since UNIX epoch: 1339089430.

level

{
    "level": "warning"
}

The record severity. Defaults to error.

level must be one of the following: debug, info, warning, error, fatal

logger

{
    "logger": "my.logger.name"
}

The name of the logger which created the record.

If missing, defaults to the string default.

culprit

{
    "culprit": "my.module.function_name"
}

Function call which was the primary perpetrator of this event.


machine

{
    "machine": {"hostname": "foo.example.com"}
}

Identifies the host client from which the event was recorded.


extra

{
    "extra": {
        "my_key": 1,
        "some_other_value": "foo bar"
    }
}

An arbitrary mapping of additional metadata to store with the event.




param_message

{
    "param_message": "My parametrized string. With %d placeholders %s"
}

A parametrized message. E.g. Could not connect to %s.

message is still required, and should be equal to the param_message, but with placeholders replaced. Opbeat will in some situations use the param_message to group errors together. The string is not interpreted by Opbeat, so feel free to use whichever placeholders makes sense in the client languange.

exception

{
    "exception": {
        "type": "ValueError",
        "value": "My exception value",
        "module": "__builtins__"
    }
}

A standard exception with mandatory type and value arguments, and an optional module argument describing the exception type’s module namespace.





stacktrace

{
    "stacktrace": {
        "frames": [{
            "abs_path": "/real/file/name.py",
            "filename": "file/name.py",
            "function": "myfunction",
            "vars": {
                "key": "value"
            },
            "pre_context": [
                "line1",
                "line2"
            ],
            "context_line": "line3",
            "lineno": 3,
            "post_context": [
                "line4",
                "line5"
            ]
        }]
    }
}

A stacktrace contains a list of frames, each with various bits (most optional) describing the context of that frame.

The stacktrace contains one element, frames, which is a list of hashes. Each hash must contain at least filename and lineno. The rest of the values are optional.











http

{
    "http": {
        "url": "http://absolute.uri/foo",
        "method": "POST",
        "data": {
            "foo": "bar"
        },
        "query_string": "hello=world&whats=up",
        "cookies": "cookie1=foo;cookie2=bar",
        "headers": {
            "Content-Type": "text/html"
        },
        "remote_host": "192.168.0.1",
        "http_host": "absolute.uri",
        "user_agent": "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)",
        "secure": true,
        "env": {
            "SERVER_SOFTWARE": "nginx",
            "GATEWAY_INTERFACE": "CGI/1.1"
        }
    }
}

If a log record was generated as a result of a http request, the http interface can be used to collect this information. Two arguments are required: url and method. url must be a complete url, with scheme, host and path.

The data variable should only contain the request body (not the query string). It can either be a dictionary (for standard HTTP requests) or a raw request body.

query_string is expected to have values delimited by ampersands (&). cookies is expected to have values delimited by semicolon (;). This is standard delimitation for query strings and the Cookie header, respectively.

headers should include any headers sent by the requester. cookies will be taken from headers if supplied.

remote_host should denominate the requesters IP address.

secure should be true if the request was an SSL/HTTPS request.

The env variable is a compounded of environment information passed from the webserver.

user

{
    "user": {
        "is_authenticated": true,
        "id": "unique_id",
        "username": "foo",
        "email": "foo@example.com"
    }
}

An interface which describes the authenticated User for a request.

All data is arbitrary and optional.




A Working Example

POST /api/v1/organization/084e240818f44e82bfae13919f55fa24/apps/7cc7083b87/error/
Authorization: Bearer b70a31b3510c4cf793964a185cfe1fd0
Host: opbeat.com
User-Agent: opbeat-curl/1.0
{
    "culprit": "my.module.function_name",
    "timestamp": "1339089430",
    "message": "SyntaxError: Wattttt!",
    "exception": {
        "type": "SyntaxError",
        "value": "Wattttt!",
        "module": "__builtins__"
    }
}

This example shows the HTTPS POST conversation with an exception, timestamp, and the mandatory message as well as the response.

Response

202 Accepted
Location: https://opbeat.com/exampleorg/exampleapp/shortcut/fc6d8c0c43fc4630ad850ee518f1b9d0

The server will repond with 202 Accepted to acknowledge the reception.

After Opbeat has recieved an error record, we will queue it for processing. Thus, there can be a slight delay until the record shows up in results, while it is being processed.

The response will contain the Location header with a link to the error detail page on Opbeat.