Skip to main content

Check out Port for yourselfย 

Setup backend

The automation's backend is the logic that you want to execute when a trigger event occurs. It will run on all entities tied to the blueprint specified in the automation's definition, whenever the trigger event occurs.

Port uses the same backend types for automations and for self-service actions.

Backend JSON structureโ€‹

The backend is defined under the invocationMethod key in the automation's JSON structure:

{
"identifier": "unique_id",
"title": "Title",
"icon": "icon_identifier",
"description": "automation description",
"trigger": {
"type": "automation",
"event": {
"type": "event_type",
"blueprintIdentifier": "blueprint_id"
},
"condition": {
"type": "JQ",
"expressions": ["expression1", "expression2"],
"combinator": "and"
}
},
"invocationMethod": {
"type": "WEBHOOK",
"url": "https://example.com",
"headers": {
"RUN_ID": "{{ .run.id }}"
},
"body": {
"payload_key": "{{ some-jq-value }}"
}
},
"publish": false
}

Supported backendsโ€‹

The type field defines the action's backend type, and can have one of the following values: WEBHOOK, GITHUB, GITLAB, KAFKA, UPSERT_ENTITY.

Depending on the backend type you choose, the available fields will be different:

invocationMethod.type should be set to WEBHOOK.

FieldTypeDescriptionExample values
agentbooleanDefines whether to use Port Agent for execution or not.true or false
urlstringDefines the webhook URL to which Port will send the action via an HTTP POST request.https://example.com
methodstringDefines the HTTP method to be used for the request.POST, PUT, DELETE, PATCH
synchronizedbooleanIf true, the action will be executed synchronously.true or false
headersobjectAn object containing the payload headers to be sent to the webhook in each execution, in "key":"value" pairs.
bodyobjectDefines the payload that will be sent to the backend upon execution of the action.
An object containing "key":"value" pairs.

To read more about each backend type, see the backend types page.

Define the payloadโ€‹

When creating a self-service action or automation, you can construct a JSON payload that will be sent to your backend upon every execution. You can use this to send data about the automation that you want your backend to have.

The payload is defined under the invocationMethod object in the automation's JSON structure. The key under which the payload is defined depends on the backend you are using (see the table above).

The payload is defined using JSON, and accessing your data is done using jq, wrapping each expression with {{ }}.

For example, the following payload definition will send a timestamp of when the execution was triggered:

{
"execution_time": "{{ .trigger.at }}",
"port_context": {
"run_id": "{{ .run.id }}"
}
}

You may have noticed that the example above also sends {{ .run.id }}. This is a unique identifier for each execution of the action, and can be used to interact with the action run in Port from your backend.

The data that is available to you when constructing the payload is detailed in the Trigger data section below.

Trigger dataโ€‹

When a self-service action or automation is executed, Port creates an object that contains data about the execution.

This entire object is accessible to you when constructing the payload.
Depending on the trigger type, the object's structure will differ:

Below is an example of trigger data for an automation that triggers whenever a service entity is updated:

{
"inputs": null,
"trigger": {
"by": {
"orgId": "org_BneDtWovPqXaA2VZ",
"userId": "auth0|62ceaea697ca00f09d7c4f45",
"user": {
"email": "example-user@test.com",
"firstName": "SomeFirstName",
"lastName": "SomeLastName",
"phoneNumber": "",
"picture": "",
"providers": [],
"status": "ACTIVE",
"id": "auth0|62ceaea697ca00f09d7c4f45",
"createdAt": "2024-06-09T09:57:50.444Z",
"updatedAt": "2024-06-09T09:57:50.444Z"
}
},
"origin": "AUTOMATION",
"at": "2024-06-09T12:28:18.663Z"
},
"event": {
"action": "UPDATE",
"resourceType": "entity",
"trigger": {
"by": {
"orgId": "org_BneDtWovPqXaA2VZ",
"userId": "auth0|62ceaea697ca00f09d7c4f45"
},
"origin": "UI",
"at": "2024-06-09T12:28:18.477Z"
},
"context": {
"blueprintIdentifier": "service",
"entityIdentifier": "example-service-identifier",
"propertyIdentifier": null
},
"diff": {
"before": {
"identifier": "example-service-identifier",
"title": "Example service",
"icon": null,
"blueprint": "service",
"team": [
"Rocket"
],
"properties": {
"latestVersion": "12.8.2",
"language": "TypeScript",
"one_hop_service_language": "Ruby",
"two_hops_service_language": "Ruby",
"repo": "https://github.com/some-org/example-service"
},
"relations": {
"using": "rogue-service"
},
"createdAt": "2024-06-09T09:57:52.931Z",
"createdBy": "60EsooJtOqimlekxrNh7nfr2iOgTcyLZ",
"updatedAt": "2024-06-09T09:57:52.931Z",
"updatedBy": "60EsooJtOqimlekxrNh7nfr2iOgTcyLZ"
},
"after": {
"identifier": "example-service-identifier",
"title": "Example service renamed",
"icon": "Microservice",
"blueprint": "service",
"team": [
"Rocket"
],
"properties": {
"latestVersion": "12.8.22",
"language": "Python",
"one_hop_service_language": "Ruby",
"two_hops_service_language": "Ruby",
"repo": "https://github.com/some-org/example-service"
},
"relations": {
"using": "rogue-service"
},
"createdAt": "2024-06-09T09:57:52.931Z",
"createdBy": "60EsooJtOqimlekxrNh7nfr2iOgTcyLZ",
"updatedAt": "2024-06-09T12:28:18.628Z",
"updatedBy": "auth0|62ceaea697ca00f09d7c4f45"
}
}
},
"entity": null,
"action": {
"identifier": "automation"
},
"run": {
"id": "r_k86OUzq80jRlxFV0"
}
}

The example above is for an automation that uses the ENTITY_UPDATED trigger event. The event.diff object contains data from before and after the update.

The other trigger events have the same structure, with the following differences:

  • ENTITY_CREATED - In the diff object, before will be null, and after will contain the new entity data.

  • ENTITY_DELETED - In the diff object, before will contain the entity data before deletion, and after will be null.

  • ANY_ENTITY_CHANGE - The diff object will contain before and/or after data according to the entity change.

  • TIMER_PROPERTY_EXPIRED - In the diff object, there will be an after object containing the entity data.

Using secrets in the payloadโ€‹

Sensitive data such as tokens and passwords can be stored using Port secrets.

To use a secret in the payload, you can reference it using {{ .secrets.<secret_name> }}.

For example:

"token": "{{ .secrets.token_name }}"

spreadValue() functionโ€‹

You can use the spreadValue() function to add multiple keys to the root of the payload at once. This function will spread all of the keys under a given object.
A common use case for this function is to add all of the user inputs to the payload:

{
"{{ spreadValue() }}": "{{ .inputs }}"
}

This will add all of the action's user inputs to the root of the payload, so that they can be accessed directly by your backend.

Using jq expressions in keysโ€‹

The keys in the payload can also be jq expressions.
For example, the following expression will add the ref key to the payload only if a ref input was provided when executing the action:

{
"{{if (.inputs | has(\"ref\")) then \"ref\" else null end}}": "{{.inputs.ref}}"
}
Using jq in keys

Note that if a key in the payload evaluates to null for any reason, the entire expression (key + value) will be omitted from the payload.