Request

POST /events/request

Overview

The POST /events/request API can be used to programmatically send a Sym Request.

The Open API Spec and and example requests are available here: Initialize a Sym request

Request Body Parameters

The request body consists of the following parameters: flow_srn, flow_inputs, context, and one of user_email or user_id.

flow_srn (required)

The required flow_srn parameter is the SRN of the Flow you would like to invoke. You can find this SRN with the symflow CLI

symflow resources list sym_flow

Example output:

SRN                                   Slug
-----------------------------------   --------------------
sym:flow:flow_selection:1.0.0         flow_selection
healthyhealth:flow:my_fun_flow:2.0.0  my_fun_flow

📘

Use the latest version for your API calls!

All SRNs include a semver style version (1.0.0) indicating the version of the resource. For your API calls we recommend using latest as the version, so that you don't need to update your request body if you update your Flow!

e.g. healthyhealth:flow:my_fun_flow:latest instead of healthyhealth:flow:my_fun_flow:2.0.0

flow_inputs (required)

The required flow_inputs parameter is a JSON-object that includes all of the fields required to run your Flow. This object will change based on the prompt_field blocks you have defined for your Flow in Terraform.

For example, given the following sym_flow resource:

resource "sym_flow" "this" {
  name  = "my_fun_flow"
  label = "My Fun Flow"
  implementation = file("${path.module}/impl.py")
  environment_id = var.sym_environment.id

  params {
    strategy_id = sym_strategy.this.id

    prompt_field {
      name     = "reason"
      type     = "string"
      required = true
    }
  
    prompt_field {
      name           = "urgency"
      type           = "list"
      required       = false
      allowed_values = ["Normal", "Emergency"]
    }
  }
}

The flow_inputs object will look something like

"flow_inputs": {
  // reason is required in prompt_fields
  "reason": "Testing out Sym APIs!",  

  // urgency is defined in prompt_fields, but can be omitted because required = False!
  "urgency": "Normal",

  // required because strategy_id is defined for this sym_flow
  "target_srn": "healthyhealth:access_target:aws_iam_group:my_fun_flow_target:latest",

  // required because schedule_deescalation = True by default
  "duration": 3600
}

You might notice there are two fields that are required in this flow_inputs example, but not defined as a prompt_field:

  • target_srn: The SRN of a sym_target associated with the sym_strategy configured for this sym_flow. This SRN can be obtained with symflow resources list sym_target. This field is required because the flow has a strategy_id defined in the params block.
    • Note: The target_srn must match a sym_target listed in the sym_strategy for the Flow!
  • duration: The duration of escalation in seconds. This field is required because the Flow has schedule_deescalation = True by default.

More information about the various ways to configure a sym_flow resource's params can be found here: Flow Params.

👍

Tip: An easy way to visualize the flow_inputs block

The flow_inputs block is essentially a JSON-object representing the values you would normally input in the Slack Request Modal! If you are having trouble figuring out the values you need, just run the Flow with /sym in Slack and take a peek at the fields that are prompted by the Request Modal!

(If your Flow isn't available in the Flow Selection Modal, make sure slack is specified in allowed_sources)

context (optional)

The context block is a "bag-of-stuff" JSON object that can contain any additional values that you wish to pass to your request, but are not necessarily prompt fields. For example, if you wanted to pass through a triggered_by value, but don't want this value to be displayed in the request message posted to the Slack, then you can add it to the context block.

For example:

"context": {
  "triggered_by": "sym-implementer",
  "jira_ticket": "SYM-123"
}

These values can then be accessed in your impl.py with evt.get_context("request")

For example:

@hook
def on_approve(evt):
  request_context = evt.get_context("request")
  print(request_context["triggered_by"])
  print(request_context["jira_ticket"])

user_email or user_id (optional)

If you wish to make a request on behalf of another User, you may optionally specify a user_email or user_id identifying the User. Where

  • user_email: The User's Sym identity email
  • user_id: The User's Sym ID (a UUID)

Only one of these may be specified, and must identify a user in your organization. If specified, then this User will be set as the Requester, and will be the User that is escalated/de-escalated. If not specified, then the Bot User identified by the SYM_JWT will be the Requester.

For Example:

"user_email": "[email protected]"

or

"user_id": "115217e7-c831-4ae3-8d74-000b253384a1"

Full Request Body Example

Putting all these parts together, the request body will look something like

{
  "flow_srn": "healthyhealth:flow:my_fun_flow:latest",

  "flow_inputs": {
    "reason": "Testing out Sym APIs!",  
    "urgency": "Normal",
    "target_srn": "healthyhealth:access_target:aws_iam_group:my_fun_flow_target:latest",
    "duration": 3600
  },

  "context": {
  	"triggered_by": "sym-implementer",
    "jira_ticket": "SYM-123"
  },
    
  "user_email": "[email protected]"
}

Request Body Validation Rules

The values in flow_inputs will be validated based on the configuration defined in your sym_flow resource's prompt_field blocks.

  1. If a field is required = True, then it must be included in flow_inputs
  2. The value must match the type defined on the field. (e.g. if type = int, then the value must be an integer)
  3. If a field has allowed_values specified, then the value must match one of the allowed_values (case-sensitive)
  4. If the flow has a strategy_id defined, then target_srn must be included in flow_inputs
  5. If the flow has a duration (i.e. schedule_deescalation is True or not defined), then duration in seconds must be included in flow_inputs

Example

If we apply these rules to our example symflow defined above:

  1. reason is must be defined, because required = True
  2. urgency can be omitted, because required = False
  3. If urgency is specified, then the value must be one of Normal or Emergency
  4. target_srn must be included in flow_inputs because strategy_id is defined
  5. duration must be defined because schedule_deescalation is not defined, and therefore defaults to Truel

Response Body

The response body will echo your request and include a event_id and run_id.

  • The event_id is the ID of the specific request Event and can be used in the Get Event Status API.
  • The run_id is the ID of the Run that is initiated and can be used in:
    • The Get Run Status API to view the status of the entire Run.
    • The De-escalate API to revoke access after approval/escalation.

For example:

{
  "request": {
    "flow_srn": "healthyhealth:flow:my_fun_flow:latest",

    "flow_inputs": {
      "reason": "Testing out Sym APIs!",  
      "urgency": "Normal",
      "target_srn": "healthyhealth:access_target:aws_iam_group:my_fun_flow_target:latest",
      "duration": 3600
    },

    "context": {
      "foo": "bar",
      "jira_ticket": "SYM-123"
    }
  },
  "event_id": "c14133a1-0df1-446e-bafd-b70cc6b3db99",
  "run_id": "b8d4b0ce-0971-4aec-88e5-971b70fa0066"
}

Error Response Example

If your request does not pass input validation, then you will receive a 400 Bad Request response with a message indicating what errors occurred.

For example:

{
    "error": true,
    "message": "Invalid value for field urgency. Got 'foo', Expected one of ['Normal', 'Emergency']",
    "code": "RequestAPI:INVALID_FLOW_INPUTS",
    "status_code": 400
}

What’s Next