REST API

HMAC Auth

API requests which require API key auth will have an extra AUTHORIZATION HTTP header. It looks like this:

AUTHORIZATION: hmac $application:$payload

$payload is a base64 encoded hmac sha512 digest of the following string with the app’s API key. In the resulting base64 string, instances of + are replaced with - and / are replaced with _.

HMAC($api_key, "$window $httpMethod $path $body")

$window is the current unix timestamp in seconds, divided by 5, floor’d.

$httpMethod is generally POST

$path is the path portion of the URL, such as /v0/incidents

$body is generally the json-formatted post body.

Example client implementations:

Query Filters

Iris has a number of search endpoints allowing filtering based on data attributes. For each allowable attribute, filters are defined via the query string, with syntax in the form of $ATTRIBUTE__$OPERATOR=$ARGUMENT e.g. created__ge=123. The following operators are allowed:

  • “eq”: $ATTRIBUTE == $ARGUMENT
  • “in”: $ATTRIBUTE is contained in $ARGUMENT, which must be a list
  • “ne”: $ATTRIBUTE != $ARGUMENT
  • “gt”: $ATTRIBUTE > $ARGUMENT
  • “ge”: $ATTRIBUTE >= $ARGUMENT
  • “lt”: $ATTRIBUTE < $ARGUMENT
  • “le”: $ATTRIBUTE <= $ARGUMENT
  • “contains”: $ATTRIBUTE contains the substring $ARGUMENT. Only defined on string-like attributes
  • “startswith”: $ATTRIBUTE starts with $ARGUMENT. Only defined on string-like attributes
  • “endswith”: $ATTRIBUTE ends with $ARGUMENT. Only defined on string-like attributes

If no operator is defined (e.g. id=123), the operator is assumed to be “eq” (equality).

Routes

/v0/plans

GET /v0/plans

Plan search endpoint.

Example request:

 GET /v0/plans?name__contains=foo&active=1 HTTP/1.1

**Example response**:

.. sourcecode:: http

   HTTP/1.1 200 OK
   Content-Type: application/json

   [
       {
           "description": "This is plan foo",
           "threshold_count": 10,
           "creator": "user1",
           "created": 1478154275,
           "aggregation_reset": 300,
           "aggregation_window": 300,
           "threshold_window": 900,
           "tracking_type": null,
           "tracking_template": null,
           "tracking_key": null,
           "active": 1,
           "id": 123456,
           "name": "foo-sla0"
       }
   ]

You can also search for plans that have specific targets in their steps by using the field ‘target’

example request

GET /v0/plans?target=foo&active=1 HTTP/1.1

POST /v0/plans

Plan create endpoint. Plans can either be static, defining role/targets in plan creation, or dynamic, leaving these fields blank during creation and determining role/targets at incident creation time. Static plan example:

Example request:

POST /v0/plans HTTP/1.1

{
    "aggregation_reset": 300,
    "aggregation_window": 300,
    "creator": "user-foo",
    "description": "this is a plan",
    "name": "plan-foo",
    "steps": [
        [
            {
                "priority": "urgent",
                "repeat": 0,
                "role": "user",
                "target": "demo",
                "template": "template-foo",
                "wait": 0
                "optional": 0
            }
        ]
    ],
    "threshold_count": 10,
    "threshold_window": 900
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json

1

Aggregation: If a user receives more than $threshold_count messages from this plan via a given medium within $threshold_window seconds, group their messages for $aggregation_window seconds. After $aggregation_reset seconds without a message, aggregation stops.

For a static plan, “steps” should be a list of arrays of JSON objects defining “priority”, “repeat”, “role”, “target”, “template”, and “wait”. Each array of objects represents a step in the plan, with the JSON objects representing the notifications delivered in that step. These notifications occur in parallel with one another within a given step. Descriptions of these parameters:

priority:Priority of messages sent by this step sub-part
repeat:Number of times this message will be repeated (e.g. repeat == 0 => 1 message)
role:Role of the target
target:Name of the target
template:Name of the template user to format this message
wait:Time to wait until sending a repeat message or moving on to the next plan step.

Dynamic plan example:

Example request:

POST /v0/plans HTTP/1.1

{
    "aggregation_reset": 300,
    "aggregation_window": 300,
    "creator": "user-foo",
    "description": "this is a plan",
    "isValid": true,
    "name": "plan-foo",
    "steps": [
        [
            {
                "dynamic_index": 0,
                "priority": "urgent",
                "repeat": 0,
                "template": "template-foo",
                "wait": 0
                "optional": 0
            }
        ]
    ],
    "threshold_count": 10,
    "threshold_window": 900
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json

1

For dynamic plans, step sub-parts define a “dynamic index” rather than a role/target combination. These indices must span a range from 0..n, where n is the largest dynamic index provided. At incident creation time, a mapping of dynamic index to role/target is provided to define the recipient of a message. See incidents POST endpoint for details.

The total time of all plan steps can not exceed 24 hours.

Request Headers:
 

/v0/incidents

GET /v0/incidents

Search for incidents. Returns a list of incidents matching specified parameters. Valid parameters are listed below:

Example request:

GET /v0/incidents?owner=jdoe&created__gt=1487466146&fields=id,owner  HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "id": 123,
        "owner": "jdoe"
    },
    {
        "id": 124,
        "owner": "jdoe"
    }
]
Status Codes:

Allowed filter parameters:

  • id: Incident id (int)
  • created: Incident creation time, in seconds since Unix epoch (int)
  • owner: Username of person who claimed the incident (string)
  • updated: Time when incident was last updated (e.g. claimed), in seconds since epoch (int)
  • active: Incident status. Incidents are active if unclaimed, and inactive if they are claimed or finished with their escalation plan (0 or 1 for inactive/active, respectively)
  • context: JSON string representing the incident context data
  • application: Application that created this incident (string)
  • plan: Escalation plan name (string)
  • plan_id: Escalation plan id (int)

This endpoint also allows specification of a limit via another query parameter, which limits results to the N most recent incidents. Calls to this endpoint that do not specify either a limit or a filter will be rejected. To specify which incident attribute should be included in the output, the “fields” query parameter can be used. The fields parameter takes the value of a comma-separated list of attributes (e.g. id,owner), and the API will only include these incident fields in the output. If no “fields” value is specified, all fields will be returned.

POST /v0/incidents

Create incidents. Id for the new incident will be returned.

Example request:

POST /v0/incidents HTTP/1.1
Content-Type: application/json

{
    "plan": "test-plan",
    "context": {"number": 1, "str": "hello"}
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json

1
statuscode 201:incident created
statuscode 400:invalid request
statuscode 404:plan not found
statuscode 401:application is not allowed to create incident for other application

A request is considered invalid if:

  • plan name is missing
  • application is invalid
  • context json blob is longer than 655355 bytes
  • none of the templates used in the plan supports the given application

To create an incident for a dynamic plan (one that defines dynamic targets), an additional dynamic_targets field must be passed along with the plan and context. Consider a dynamic plan defining two dynamic targets, indexed with 0 and 1. The dynamic_targets parameter should take the following form:

[
    {
        "role": "user",
        "target": "jdoe"
    },
    {
        "role": "team",
        "target": "team-foo"
    }
]

This will map target 0 to the user “jdoe”, and target 1 to the team “team-foo”.

Request Headers:
 
GET /v0/incidents/{incident_id}

Get incident by ID.

Example request:

GET /v0/incident/1 HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "updated": 1492057026,
    "plan_id": 48271,
    "created": 1492055912,
    "application": "Alert manager",
    "steps": [
         {
             "name": "alice",
             "created": 1492055953,
             "target_changed": 0,
             "mode_changed": 0,
             "priority": "urgent",
             "step": 1,
             "mode": "sms",
             "id": 25443689,
             "sent": 1492055957
         }
    ],
    "plan": "test-plan",
    "context": {"number": 1, "str": "hello"},
    "owner": "alice",
    "active": 0,
    "id": 1,
    "current_step": 1
}
POST /v0/incidents/{incident_id}

Claim incidents by incident id. Deactivates the incident and any associated messages, preventing further escalation.

Example request:

POST /v0/incidents/123 HTTP/1.1
Content-Type: application/json

{
    "owner": "jdoe"
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "incident_id": "123",
    "owner": "jdoe",
    "active": false
}
Request Headers:
 

/v0/messages

GET /v0/messages/{message_id}

Get information for an iris message by id

Example request:

GET /v0/messages/{message_id} HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "body": "message body",
   "incident_id": 2590447,
   "target": "username",
   "created": 1490825218,
   "destination": "username@domain.com",
   "batch": null,
   "twilio_delivery_status": null,
   "priority": "low",
   "application": "app",
   "mode": "email",
   "active": 0,
   "generic_message_sent_status": 1,
   "id": 24807074,
   "sent": 1490825221,
   "subject": "message subject"
}
GET /v0/messages/{message_id}/auditlog

Get a message’s log of changes

Example request:

GET /v0/messages/{message_id}/auditlog HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "old": "sms",
    "description": "Changing mode due to original mode failure",
    "date": 1489507284,
    "new": "email",
    "change_type": "mode-change",
    "id": 438
  },
]

/v0/notifications

POST /v0/notifications

Create out of band notifications. Notification is ad-hoc message that’s not tied to an incident. To achieve real-time delivery, notifications are not persisted in the Database.

You can set the priority key to honor target’s priority preference or set the mode key to force the message transport.

You can use the role “literal_target” to prevent unrolling of targets and send messages directly to mailing lists or slack channels. Note that if you use this role you MUST specify the mode key but not the priority. This role will set the destination to the target value so make sure the target is a valid email address, slack channel, slack username, etc.

If you define a category users will be able to define how they wish to receive that notification by category. To use a category you must first define it for your application from your application page or through an api call.

Multi-recipient messages are supported for notifications explicitly specifying the “email” mode. To send a multi-recipient message, specify a list of objects defining “role” and “target” attributes. All roles, including “literal_target”, are supported. These messages will be sent on a best-effort basis to as many targets as is possible. If any role:target pairs are found to be invalid, they will be skipped, and the message will be delivered to all other targets. Each object can also optionally define a “bcc” field, which will mark those targets as bcc if set to true. If no bcc attribute is defined for a target, the default value is false.

Example request:

POST /v0/notifications HTTP/1.1
Content-Type: application/json

{
    "role": "secondary-oncall",
    "target": "test_oncall_team",
    "subject": "wake up",
    "body": "something is on fire",
    "priority": "high"
}
POST /v0/notifications HTTP/1.1
Content-Type: application/json

{
    "role": "user",
    "target": "test_user",
    "subject": "wake up",
    "body": "something is on fire",
    "mode": "email"
}
POST /v0/notifications HTTP/1.1
Content-Type: application/json

{
    "role": "user",
    "target": "test_user",
    "subject": "wake up",
    "body": "something is on fire",
    "category": "category_name"
}
POST /v0/notifications HTTP/1.1
Content-Type: application/json

{
    "role": "literal_target",
    "target": "#slackchannel",
    "subject": "wake up",
    "body": "something is on fire",
    "mode": "slack"
}
POST /v0/notifications HTTP/1.1
Content-Type: application/json

{
    "target_list": {
        {
            "role": "literal_target",
            "target": "list@example.com"
        },
        {
            "role": "user",
            "target": "jdoe",
            "bcc": true
        }
    }
    "subject": "wake up",
    "body": "something is on fire",
    "mode": "email"
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[]
statuscode 200:notification send request queued
statuscode 400:invalid request
statuscode 401:application is not allowed to create out of band notification

A request is considered invalid if:

  • either target, subject or role is missing and target_list is not provided
  • target_list is provided, but no subject
  • target_list is malformed (not of the form [{“role”: foo, “target”: bar}])
  • a priority is given for a target_list
  • both priority and mode are missing
  • invalid priority, mode
  • both template, body and email_html are missing
  • template, body and email_html is not a string
  • message queue request rejected by sender
Request Headers:
 

/v0/target_roles

GET /v0/target_roles

Target role fetch endpoint.

Example request:

GET /v0/target_roles HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "name": "user",
        "type": "user"
    },
    {
        "name": "oncall",
        "type": "team"
    }
]

/v0/users

DELETE /v0/users/{username}/categories

Delete a user’s category settings for a given app, removing all overrides for that app. Essentially sets all categories back to default.

Example request:

DELETE /v0/users/jdoe/categories/foo-app HTTP/1.1

Example response:

HTTP/1.1 204 No Content
Content-Type: application/json
Request Headers:
 
GET /v0/users/{username}/categories

Get notification category overrides by user. Returns a list of override objects, defining the app, category, and override mode. If no application is provided in the URL, returns all category overrides for the user.

Example request:

GET /v0/users/jdoe/categories/foo-app HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "application": "foo-app",
        "category": "bar-category",
        "mode": "drop"
    }
]
Request Headers:
 
POST /v0/users/{username}/categories

Create and edit a user’s overrides for an application. Takes a mapping of category_name: mode. For each category passed, either creates or overwrites the user’s settings for that category, mapping it to the given mode. If the mode is null/None, instead deletes that mapping to revert the category setting to default. e.g. passing {“foo”: “email”, “bar”: None} will delete the setting for “bar” and map “foo” to “email”, regardless of whether “foo” previously had another setting.

Example request:

POST /v0/categories/123 HTTP/1.1
Content-Type: application/json

{
    "foo-category": "drop",
    "bar-category": null,
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Request Headers:
 
DELETE /v0/users/{username}/categories/{application}

Delete a user’s category settings for a given app, removing all overrides for that app. Essentially sets all categories back to default.

Example request:

DELETE /v0/users/jdoe/categories/foo-app HTTP/1.1

Example response:

HTTP/1.1 204 No Content
Content-Type: application/json
Request Headers:
 
GET /v0/users/{username}/categories/{application}

Get notification category overrides by user. Returns a list of override objects, defining the app, category, and override mode. If no application is provided in the URL, returns all category overrides for the user.

Example request:

GET /v0/users/jdoe/categories/foo-app HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "application": "foo-app",
        "category": "bar-category",
        "mode": "drop"
    }
]
Request Headers:
 
POST /v0/users/{username}/categories/{application}

Create and edit a user’s overrides for an application. Takes a mapping of category_name: mode. For each category passed, either creates or overwrites the user’s settings for that category, mapping it to the given mode. If the mode is null/None, instead deletes that mapping to revert the category setting to default. e.g. passing {“foo”: “email”, “bar”: None} will delete the setting for “bar” and map “foo” to “email”, regardless of whether “foo” previously had another setting.

Example request:

POST /v0/categories/123 HTTP/1.1
Content-Type: application/json

{
    "foo-category": "drop",
    "bar-category": null,
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Request Headers:
 
GET /v0/users/modes/{username}

Get priority:mode mappings for a given user. If no application is passed via query params, returns a user’s global priority:mode mapping. Otherwise, return the per-application priority mapping that corresponds to the specified application. Any undefined mapping has “default” specified as mode, otherwise the mode’s name is specified.

This action is only available if the request’s username matches the username passed in the URL. Admins and apps that can authenticate as users are also allowed to access this data.

Example request:

GET /v0/users/modes/jdoe?application=foo HTTP/1.1
Content-Type: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "high": "default",
    "low": "email",
    "medium": "slack",
    "urgent": "default",
}
Request Headers:
 
POST /v0/users/modes/{username}

Update priority:mode mappings for a given user. To update global priority mappings, specify the priority and new value in the base level of the post body. For per application settings, define new values in a dict mapping to the app’s name under the “per_app_modes” key. To delete settings, specify “default” as the mode mapping. Any priority/app not specified in the request is unchanged.

This API responds with the new value of the global priority:mode mapping after the request has been made.

This action is available only to the user matching the username in the URL, to admins, and to apps that can authenticate as users.

Example request:

POST /v0/notifications HTTP/1.1
Content-Type: application/json

 {
     "urgent": "default",
     "high": "slack",
     "medium": "slack",
     "low": "default",
     "per_app_modes": {
         "foo-app": {
             "urgent": "default",
             "high": "default",
             "medium": "default",
             "low": "email"
         },
         "bar-app": {
             "urgent": "default",
             "high": "default",
             "medium": "default",
             "low": "default"
         }
     }
 }

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
     "urgent": "default",
     "high": "slack",
     "medium": "slack",
     "low": "default",
 }
Request Headers:
 
DELETE /v0/users/reprioritization/{username}/{src_mode_name}

Delete a reprioritization mode for a user’s mode setting

Example request:

DELETE /v0/users/reprioritization/{username}/{src_mode_name} HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[]
Request Headers:
 

/v0/modes

GET /v0/modes

List all iris modes

Example request:

GET /v0/modes HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

["sms", "email", "slack", "call"]
Request Headers:
 

/v0/applications

GET /v0/applications/{app_name}/incident_emails

Get email addresses which will create incidents on behalf of this application

Example request:

GET /v0/applications/{app_name}/incident_emails HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "incident@fakeemail.cde": "page_oncall_plan",
  "audit@fakeemail.abc": "audit_plan"
}
Request Headers:
 
GET /v0/applications/{app_name}/plans

Search endpoint for active plans that support a given app. A plan supports an app if one of its steps uses a template that defines content for that application.

Example request:

GET /v0/applications/app-foo/plans?name__contains=bar& HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "description": "This is plan bar",
        "threshold_count": 10,
        "creator": "user1",
        "created": 1478154275,
        "aggregation_reset": 300,
        "aggregation_window": 300,
        "threshold_window": 900,
        "tracking_type": null,
        "tracking_template": null,
        "tracking_key": null,
        "active": 1,
        "id": 123456,
        "name": "bar-sla0"
    }
]

/v0/categories

GET /v0/categories

Notification category search. Can filter based on id, name, app name, and mode. Returns a list of categories matching the specified filters.

Example request:

GET /v0/categories?name__startswith=foo&application=app HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "id": 123,
        "name": "foobar",
        "application": "app",
        "mode": "email"
    }
]
POST /v0/categories

Create notification categories for a given app. Pass a list of categories representing all notification categories for the app. This endpoint will create, edit, and delete the app’s categories to match the list passed in.

Example request:

POST /v0/categories/foo-app HTTP/1.1
Content-Type: application/json

 [
    {
         "name": "foo-category",
         "description": "foobar",
         "mode": "email"
     },
     {
         "name": "bar-category",
         "description": "barbaz",
         "mode": "slack"
     }
 ]

Example response:

HTTP/1.1 200 OK
Content-Type: application/json
statuscode 200:categories saved
statuscode 400:invalid request, missing required attributes
statuscode 401:user/app is not allowed to create categories for this app
Request Headers:
 
GET /v0/categories/{application}

Notification category search. Can filter based on id, name, app name, and mode. Returns a list of categories matching the specified filters.

Example request:

GET /v0/categories?name__startswith=foo&application=app HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "id": 123,
        "name": "foobar",
        "application": "app",
        "mode": "email"
    }
]
POST /v0/categories/{application}

Create notification categories for a given app. Pass a list of categories representing all notification categories for the app. This endpoint will create, edit, and delete the app’s categories to match the list passed in.

Example request:

POST /v0/categories/foo-app HTTP/1.1
Content-Type: application/json

 [
    {
         "name": "foo-category",
         "description": "foobar",
         "mode": "email"
     },
     {
         "name": "bar-category",
         "description": "barbaz",
         "mode": "slack"
     }
 ]

Example response:

HTTP/1.1 200 OK
Content-Type: application/json
statuscode 200:categories saved
statuscode 400:invalid request, missing required attributes
statuscode 401:user/app is not allowed to create categories for this app
Request Headers:
 

/healthcheck

GET /healthcheck

Healthcheck endpoint. Returns contents of healthcheck file.

Example request:

GET /v0/healthcheck HTTP/1.1

Example response:

HTTP/1.1 200 OK
Content-Type: text/plain

GOOD