Skip to main content

Setup backend


A self-service action's backend is the logic that runs when the action is triggered. The implementation of the backend is done by you, using one of the various backend types that Port supports.

Identical backends for self-service actions and automations

Port uses the same backend types and configurations for both self-service actions and automations, so any backend option available for self-service actions can be used in automations as well.

Define the backend

The action's backend is defined under the Backend tab of the action creation form in Port's UI.
Let's break the definition down to two parts:

Define your backend's type and metadata

In this section we provide information about the backend logic and its location, so that Port can access and run it.

Port uses the same backend types for both self-service actions and automations.
For more information and examples for the available backend types, check out the Backend types page.

Here is an example of a Github workflow backend configuration:



Depending on the backend type you choose, you will need to provide different configuration parameters.

Define the action's 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 action that you want your backend to have.

Still in the Backend tab, scroll down to the Configure the invocation payload section. This is where we define the action's payload.

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

For example, say we have an action with one user input that is the user's name. The following payload definition will send the name provided by the executor to the backend upon every execution:

{
"user_name": "{{ .inputs.user_name }}",
"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.

Now you might be thinking - how do I know what data is available to me when constructing the payload?
Enter trigger data.

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.
Here is an example of what trigger data could look like for a self-service action that scaffolds a new microservice:

{
// The action's user inputs
"inputs": {
"microservice_name": "string",
"microservice_description": "string",
"language": "string",
"version": "string",
"core": "string",
"features": "string"
},
"trigger": {
"by": {
"orgId": "<Your organization's id>",
"userId": "<Executing user's id>",
"user": {
"email": "<Executing user's email>",
"firstName": "<Executing user's firstName>",
"lastName": "<Executing user's lastName>",
"phoneNumber": "<Executing user's phoneNumber>",
"picture": "",
"providers": [],
"status": "ACTIVE",
"id": "<Executing user's id>",
"createdAt": "2024-06-06T05:21:00.565Z",
"updatedAt": "2024-06-06T05:21:00.565Z"
}
},
"origin": "UI",
"at": "2024-06-06T05:21:00.565Z",
"operation": "CREATE"
},
"event": null,
"entity": {},
"action": {
"identifier": "Microservice_scaffold_a_microservice",
"blueprint": "Microservice",
"encryptedProperties": []
},
"run": {
"id": "<The current run's id>"
}
}

You can access any value in this structure and add it to the payload. For example, to add the executing user's name to the payload, you can use the following expression:

{
"executing_user_email": "{{.trigger.by.user.email}}"
}

Use the Test JQ button in the bottom-left corner to test your expressions against your action and ensure you are sending the correct data.

Pro tip

You can use the jq expression {{ . }} when testing to see the entire available object, and then drill down to the specific data you need.

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 ommitted from the payload.

JSON structure

In some cases, you may prefer to define the backend configuration using a JSON object.
The backend is defined under the invocationMethod object in the action's JSON structure.

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.

Next step

Once the backend is set up, the action is ready to be used.
Optionally, you can configure permissions and/or manual approval for your actions to control who is allowed to execute them.