Service Creation Webhook Context Schema

A service template's post-service creation webhook's request payload and rendered response support liquid templating. When firing the webhook, they receive a context object. This allows the webhook to behave dynamically based on the information in the context.

Context fields are accessed using Liquid's double handle bar notation: {{ identifier }}. When evaluated this would be replaced by the matching value in the context.

The service creation webhook context contains the following properties:

Service

When a template successfully executes, a new OpsLevel service is created. The webhook that can be optionally fired after that will have access to the context of the new service. These properties all refer to that service. For more information on how to configure a post-service creation webhook, see the guide to getting started with service creation.

Description
service.frameworkThe primary software development framework that the service uses.
service.hrefA link to the HTML page for the service.
service.idThe unique identifier for the service.
service.languageThe primary programming language that the service is written in.
service.lifecycle_indexThe lifecycle stage of the service.
service.nameThe display name of the service.
service.productA product is an application that your end user interacts with. Multiple services can work together to power a single product.
service.service_repositoriesA list of repositories that are linked to the service. For details on what values are available on the repository, see Service Repositories.
service.slugThe URL friendly name of the service.
service.tier_indexThe software tier that the service belongs to.
service.ownerAn object representing the team that owns the service. For details on what values are available on the owner, see Owner.

Service Repository

When a service is created from a template, a new repository is created and associated with the service. The new repository's details will also be available to the webhook.

Description
service_repository.is_primaryIf true, the repository is considered the main source code for the service.
service_repository.display_nameThe name of the repository as it is displayed in OpsLevel.
service_repository.deep_urlAn HTTP URL to the repository in the external Git Forge.
service_repository.repository.default_branchThe name of the default branch for the repository.

Template Run

The webhook is fired after a successful "template run" - i.e., a successful execution of the underlying cookiecutter template. The webhook context can access the inputs to and the outputs from the template run.

Template Run Inputs

The inputs to a template run are the values entered for the fields defined in the template's cookiecutter.json file. These are dynamically attached to the template_run.inputs field in the context.

Description
template_run.inputs.{field_name}Value of the input for "{field_name}" variable defined in the template's cookicutter.json file.

For example, if one of the template input variables was called "project_name", the value entered for that could be accessed in the Liquid template under "template_run.inputs.project_name".

Template Run Outputs

Every template run generated from the git forge write flow preceding a post-service creation webhook will have created a new repository for the service and an initial pull/merge request against that repository that adds the all the service's initial source code generated from the cookiecutter template. References to that repository and pull/merge request is accessible from the webhook's context.

Description
template_run.outputs.repo_urlURL to the new repository created in the user's git forge by the template run.
template_run.outputs.merge_request_urlURL to the initial pull request (also known as "merge request" in some git forges) created against the new repository. This initial pull request is adding all the output generated from running the underlying cookiecutter template to the initially empty repository.
template_run.outputs.merge_request_branchThe name of the branch made for the initial pull request (also known as "merge request" in some git forges) created against the new repository.

User

Service creation is invoked by an individual user. These properties all refer to that user.

Description
user.api_token_countThe number of api tokens owned by this user.
user.deactivatedTrue if this user is deactivated and cannot be used.
user.deactivated_atThe time that the user was deactivated.
user.emailThe user's email.
user.gravatar_urlThe url to the user's gravatar image.
user.has_providerWhether this user is managed externally.
user.hrefA link to the HTML page for the user.
user.idThe unique identifier for the user.
user.nameThe user's full name.
user.pendingWhether the user accepted their invitation to OpsLevel or not.
user.provisioned_byHow the user was provisioned. Possible values:, SCIM, OpsLevel CLI, Terraform, API, SSO (Okta), SSO, OpsLevel Admin, and Unknown.
user.roleThe user's assigned role.

Owner

An owner reference is the Team responsible for a component in OpsLevel. The webhook context can contain a reference to the template owner as action_owner. This field may be blank if the Team specified as the owner has been deleted from OpsLevel. Also available is the new service's owner under service.owner.

Description
action_owner.contacts
service.owner.contacts
A list of details for contacting the owner. See Contact for more details.
action_owner.href
service.owner.href
A link to the HTML page for the owner.
action_owner.id
service.owner.id
The unique identifier for the owner.
action_owner.manager
service.owner.manager
The user who manages the owner. See User for more details.
action_owner.name
service.owner.name
The display name of the owner.
action_owner.slug
service.owner.slug
A human-friendly, unique identifier.

Contact

Contacts are the communication channels used to get in touch with the template owner.

Description
contact.addressThe contact address. Examples: Email([email protected]) and Web(https://opslevel.com).
contact.contact_methodThe method of contact. Possible values:email, slack, slack_handle, and web.
contact.display_nameThe name shown in the UI for the contact.
contact.display_typeThe type shown in the UI for the contact. Possible values: Primary, Secondary, and None.
contact.idThe unique identifier for the contact.
contact.target_hrefThe fully qualified URI for the contact.

Response

The Response Details property injects an additional object into the Action’s context. These properties all refer to the response received from the webhook URL when invoking the action.

The response headers and body will be coerced into JSON if possible and can be referenced in the Liquid template as {{ response.headers.<property> }}.

Description
response.statusThe HTTP status code.
response.headersThe HTTP headers.
response.bodyThe response body.

Example Context

Post-Service Creation Webhook Context

{
  	"template_run": {
      "inputs": {
        "full_name": "First Last",
        "email": "[email protected]",
        "project_name": "Django Boilerplate",
        "django_version": "4.2.2"
      },
      "outputs": {
        "repo_url": "https://github.com/GROUP/django-boilerplate",
        "merge_request_url": "https://github.com/GROUP/django-boilerplate/pull/1",
        "merge_request_branch": "example-branch"
      }
    },
    "user":
    {
        "id": "SOME-ID",
        "name": "First Last",
        "email": "[email protected]",
        "href": "/users/SOME-ID",
        "role": "admin",
        "deactivated_at": null,
        "deactivated": false,
        "gravatar_src": "",
        "pending": false,
        "has_provider": false,
        "api_token_count": 3,
        "provisioned_by": "OpsLevel Admin"
    },
    "service":
    {
        "id": "SOME-ID",
        "name": "Django Test",
        "href": "/services/django_test",
        "product": null,
        "language": "Java",
        "framework": "Spring",
        "slug": "django_test",
        "tier_index": null,
        "lifecycle_index": null,
        "service_stat":
        {
            "num_checks": 9,
            "num_passing_checks": 4
        },
        "tags":
        [
            {
                "key": "is_approved",
                "value": "false",
                "id": "SOME-ID",
                "gid": "SOME-ID",
                "locked": false
            }
        ],
        "service_repositories":
        [
            {
                "id": 9999,
                "gid": "SOME-ID",
                "repo_path": "",
                "is_primary": false,
                "managed": false,
                "locked": false,
                "at_root": true,
                "display_name": "GROUP/django-test",
                "deep_url": "https://github.com/GROUP/django-test",
                "repository":
                {
                    "id": 9999,
                    "gid": "SOME-ID",
                    "name": "django-test",
                    "url": "https://github.com/GROUP/django-test",
                    "default_branch": "main",
                    "invalidated_at": null,
                    "active": true,
                    "forked": false,
                    "repo_key": "SOME-ID",
                    "display_name": "GROUP/django-test",
                    "description": null,
                    "type_string": "github",
                    "visible": true,
                    "archived_at": null,
                    "branch_protection": false,
                    "created_on": "2022-08-04T12:12:33.000000Z",
                    "account_name": "GROUP",
                    "type_display_name": "GitHub",
                    "icon": "github",
                    "integration_href": "https://app.opslevel.com/integrations/github/SOME-ID",
                    "locked": false,
                    "private": true,
                    "href": "/repositories/SOME-ID"
                }
            }
        ],
        "owner":
        {
            "id": "SOME-ID",
            "name": "Aes Sedai",
            "href": "/teams/aes_sedai",
            "slug": "aes_sedai",
            "service_stat":
            {
                "num_checks": 38,
                "num_passing_checks": 13
            },
            "manager":
            {
                "id": 9999999,
                "email": "[email protected]",
                "session_token": "SOME-ID",
                "last_sign_in_method": null,
                "name": "Moirane Damodred",
                "account_id": 999999,
                "accepted_tos_at": null,
                "role": "user",
                "provisioned_by_id": null,
                "provisioned_by_type": null,
                "provisioned_by_details": null,
                "deactivated_at": null,
                "created_at": "2022-06-29T22:43:06.619978Z",
                "updated_at": "2022-06-29T22:43:06.713373Z",
                "seen_team_cta": null
            },
            "tags":
            [],
            "contacts":
            [
                {
                    "id": 99999,
                    "address": "#the-white-tower",
                    "contact_method": "SLACK",
                    "display_name": "Slack Channel",
                    "display_type": null,
                    "target_href": "https://my-workspace.slack.com/channels/the-white-tower/",
                    "type": "Slack",
                    "short_name": "#the-white-tower",
                    "icon": "slack"
                }
            ]
        }
    },
    "action_owner":
    {
        "id": "SOME-ID",
        "name": "Team A",
        "href": "/teams/team_a",
        "slug": "team_a",
        "service_stat":
        {
            "num_checks": 0,
            "num_passing_checks": 0
        },
        "manager": null,
        "contacts":
        []
    },
}