Manage PagerDuty on-call schedules
This guide demonstrates how to bring your on-call management experience into Port using PagerDuty.
You will learn how to:
- Set up self-service actions to manage on-call schedules (view schedules, change on-call users, create overrides).
- Build dashboards in Port to visualize on-call coverage, rotation schedules, and team assignments.
- Track on-call engineers across different teams and services.
 
 
Common use casesโ
- On-call visibility: Get a centralized view of who's on-call across all teams and services.
- Schedule management: Easily change on-call assignments and create temporary overrides.
- Team coordination: Track on-call rotations and ensure proper coverage across services.
- Escalation planning: Visualize escalation policies and on-call hierarchies.
- Burnout prevention: Monitor on-call frequency and distribute responsibilities fairly.
Prerequisitesโ
This guide assumes the following:
- You have a Port account and have completed the onboarding process.
- Port's PagerDuty integration is installed in your account.
- Access to your PagerDuty organization with permissions to manage schedules and on-call assignments.
- Port's GitHub app needs to be installed.
Set up data modelโ
If you haven't installed the PagerDuty integration, you'll need to create blueprints for PagerDuty schedules and users.
However, we highly recommend you install the PagerDuty integration to have these automatically set up for you.
Create the PagerDuty Schedule blueprint
- 
Go to the Builder page of your portal. 
- 
Click on + Blueprint.
- 
Click on the {...}button in the top right corner, and chooseEdit JSON.
- 
Add this JSON schema: PagerDuty Schedule Blueprint{
 "identifier": "pagerdutySchedule",
 "description": "This blueprint represents a PagerDuty schedule in our software catalog",
 "title": "PagerDuty Schedule",
 "icon": "pagerduty",
 "schema": {
 "properties": {
 "url": {
 "type": "string",
 "format": "url",
 "title": "Schedule URL"
 },
 "timezone": {
 "type": "string",
 "title": "Timezone"
 },
 "description": {
 "type": "string",
 "title": "Description"
 },
 "final_schedule": {
 "type": "object",
 "title": "Final Schedule"
 },
 "overrides_subschedule": {
 "type": "object",
 "title": "Overrides"
 },
 "created_at": {
 "title": "Created At",
 "type": "string",
 "format": "date-time"
 },
 "updated_at": {
 "title": "Updated At",
 "type": "string",
 "format": "date-time"
 }
 },
 "required": []
 },
 "mirrorProperties": {},
 "calculationProperties": {},
 "relations": {
 "pagerdutyService": {
 "title": "PagerDuty Service",
 "target": "pagerdutyService",
 "required": false,
 "many": true
 }
 }
 }
- 
Click Save.
Create the PagerDuty User blueprint
- 
Go to the Builder page of your portal. 
- 
Click on + Blueprint.
- 
Click on the {...}button in the top right corner, and chooseEdit JSON.
- 
Add this JSON schema: PagerDuty User Blueprint{
 "identifier": "pagerdutyUser",
 "description": "This blueprint represents a PagerDuty user in our software catalog",
 "title": "PagerDuty User",
 "icon": "pagerduty",
 "schema": {
 "properties": {
 "email": {
 "type": "string",
 "format": "email",
 "title": "Email"
 },
 "time_zone": {
 "type": "string",
 "title": "Time Zone"
 },
 "color": {
 "type": "string",
 "title": "Color"
 },
 "role": {
 "type": "string",
 "title": "Role"
 },
 "avatar_url": {
 "type": "string",
 "format": "url",
 "title": "Avatar URL"
 },
 "description": {
 "type": "string",
 "title": "Description"
 },
 "created_at": {
 "title": "Created At",
 "type": "string",
 "format": "date-time"
 }
 },
 "required": []
 },
 "mirrorProperties": {},
 "calculationProperties": {},
 "relations": {
 "pagerdutyTeam": {
 "title": "PagerDuty Team",
 "target": "pagerdutyTeam",
 "required": false,
 "many": true
 }
 }
 }
- 
Click Save.
Set up self-service actionsโ
Now let's set up self-service actions to manage your PagerDuty on-call schedules directly from Port. We'll implement key on-call management workflows using webhook-based actions.
Add Github secretsโ
In your GitHub repository, go to Settings > Secrets and add the following secrets:
- PAGERDUTY_API_KEY- PagerDuty API token generated by the user.
- PORT_CLIENT_ID- Your port- client idHow to get the credentials.
- PORT_CLIENT_SECRET- Your port- client secretHow to get the credentials.
View current on-call userโ
Get information about who is currently on-call for a specific schedule using a GitHub workflow.
GitHub workflow
Create the file .github/workflows/view-current-oncall.yaml in the .github/workflows folder of your repository.
GitHub workflow script (click to expand)
name: View Current On-Call User
on:
  workflow_dispatch:
    inputs:
      port_context:
        required: true
        description: includes blueprint, run ID, and entity identifier from Port.
jobs:
  view-current-oncall:
    runs-on: ubuntu-latest
    steps:
      - name: Inform start of oncall lookup
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Looking up current on-call user for schedule... โด๏ธ"
      - name: Get current on-call information
        id: get_oncall
        uses: fjogeleit/http-request-action@v1
        with:
          url: "https://api.pagerduty.com/oncalls?schedule_ids[]=${{fromJson(inputs.port_context).entity}}"
          method: "GET"
          customHeaders: '{"Content-Type": "application/json", "Accept": "application/vnd.pagerduty+json;version=2", "Authorization": "Token token=${{ secrets.PAGERDUTY_API_KEY }}"}'
      - name: Extract on-call user information
        id: extract_oncall_info
        run: |
          ONCALL_DATA='${{ steps.get_oncall.outputs.response }}'
          
          # Check if there are any oncalls
          ONCALL_COUNT=$(echo "$ONCALL_DATA" | jq '.oncalls | length')
          
          if [ "$ONCALL_COUNT" -eq 0 ]; then
            echo "No one is currently on-call for this schedule"
            echo "oncall_user=No one currently on-call" >> $GITHUB_OUTPUT
            echo "oncall_start=N/A" >> $GITHUB_OUTPUT
            echo "oncall_end=N/A" >> $GITHUB_OUTPUT
            echo "escalation_level=N/A" >> $GITHUB_OUTPUT
          else
            # Get the first (primary) on-call entry
            ONCALL_USER=$(echo "$ONCALL_DATA" | jq -r '.oncalls[0].user.summary // "Unknown"')
            ONCALL_START=$(echo "$ONCALL_DATA" | jq -r '.oncalls[0].start // "Unknown"')
            ONCALL_END=$(echo "$ONCALL_DATA" | jq -r '.oncalls[0].end // "Unknown"')
            ESCALATION_LEVEL=$(echo "$ONCALL_DATA" | jq -r '.oncalls[0].escalation_level // "Unknown"')
            
            echo "oncall_user=$ONCALL_USER" >> $GITHUB_OUTPUT
            echo "oncall_start=$ONCALL_START" >> $GITHUB_OUTPUT
            echo "oncall_end=$ONCALL_END" >> $GITHUB_OUTPUT
            echo "escalation_level=$ESCALATION_LEVEL" >> $GITHUB_OUTPUT
          fi
      - name: Display on-call information
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: |
            ๐ **Current On-Call Information:**
            
            ๐ค **User:** ${{ steps.extract_oncall_info.outputs.oncall_user }}
            ๐ **Start:** ${{ steps.extract_oncall_info.outputs.oncall_start }}
            ๐ **End:** ${{ steps.extract_oncall_info.outputs.oncall_end }}
            ๐ถ **Escalation Level:** ${{ steps.extract_oncall_info.outputs.escalation_level }}
      - name: Log completion
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "On-call lookup completed successfully โ
"
Add the self-service action
- 
Head to the self-service page. 
- 
Click on the + New Actionbutton.
- 
Click on the {...} Edit JSONbutton.
- 
Copy and paste the following JSON configuration into the editor: View current on-call user (click to expand){
 "identifier": "view_current_oncall",
 "title": "View current on-call user",
 "icon": "pagerduty",
 "description": "Get information about who is currently on-call for this schedule",
 "trigger": {
 "type": "self-service",
 "operation": "DAY-2",
 "userInputs": {
 "properties": {},
 "required": [],
 "order": []
 },
 "blueprintIdentifier": "pagerdutySchedule"
 },
 "invocationMethod": {
 "type": "GITHUB",
 "org": "<GITHUB_ORG>",
 "repo": "<GITHUB_REPO>",
 "workflow": "view-current-oncall.yaml",
 "workflowInputs": {
 "port_context": {
 "blueprint": "{{.action.blueprint}}",
 "entity": "{{.entity.identifier}}",
 "run_id": "{{.run.id}}"
 }
 },
 "reportWorkflowStatus": true
 },
 "requiredApproval": false
 }
- 
Click Save.
Change on-call userโ
Change the current on-call assignment for a schedule by creating an override using a GitHub workflow.
GitHub workflow
Create the file .github/workflows/change-oncall-user.yaml in the .github/workflows folder of your repository.
GitHub workflow script (click to expand)
name: Change On-Call User
on:
  workflow_dispatch:
    inputs:
      start_time:
        description: The start time for the override, in ISO 8601 format (e.g., 2023-01-01T01:00:00Z)
        required: true
        type: string
      end_time:
        description: The end time for the override, in ISO 8601 format (e.g., 2023-01-01T01:00:00Z).
        required: true
        type: string
      new_on_call_user:
        description: The email of the user who will be taking over the on-call duty
        required: true
        type: string
      port_context:
        required: true
        description: includes blueprint, run ID, and entity identifier from Port.
jobs:
  change-on-call-user:
    runs-on: ubuntu-latest
    steps:
      - name: Inform searching of user in user list
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Searching for user in organization user list... โด๏ธ"
      - name: Search for user id among user list
        id: search_for_user_id
        uses: fjogeleit/http-request-action@v1
        with:
          url: "https://api.pagerduty.com/users?query=${{ github.event.inputs.new_on_call_user }}"
          method: "GET"
          customHeaders: '{"Content-Type": "application/json", "Authorization": "Token token=${{ secrets.PAGERDUTY_API_KEY }}"}'
      - name: Retrieve user list from search
        id: user_id_from_search
        if: steps.search_for_user_id.outcome == 'success'
        run: |
          user_id=$(echo '${{ steps.search_for_user_id.outputs.response }}' | jq -r '.users | if length > 0 then .[0].id else "empty" end')
          echo "user_id=${user_id}" >> $GITHUB_OUTPUT
      - name: Inform user existence
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: |
            User found ๐ฅน, Creating override for ${{ inputs.new_on_call_user }}... โด๏ธ
      
      - name: Inform user inexistence
        if: steps.user_id_from_search.outputs.user_id == 'empty'
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: |
            User not found ๐ญ Skipping assignment... โด๏ธ
  
      - name: Create Override in PagerDuty
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        id: create_override
        uses: fjogeleit/http-request-action@v1
        with:
          url: "https://api.pagerduty.com/schedules/${{fromJson(inputs.port_context).entity}}/overrides"
          method: 'POST'
          customHeaders: '{"Content-Type": "application/json", "Accept": "application/vnd.pagerduty+json;version=2", "Authorization": "Token token=${{ secrets.PAGERDUTY_API_KEY }}"}'
          data: >-
            {
              "override": {
                "start": "${{ github.event.inputs.start_time }}",
                "end": "${{ github.event.inputs.end_time }}",
                "user": {
                  "id": "${{ steps.user_id_from_search.outputs.user_id }}",
                  "type": "user_reference" 
                }
              }
            }
      - name: Log Before Requesting for Updated Schedule
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Getting updated schedule from PagerDuty..."
      - name: Request For Updated Schedule
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        id: new_schedule
        uses: fjogeleit/http-request-action@v1
        with:
          url: 'https://api.pagerduty.com/schedules/${{fromJson(inputs.port_context).entity}}'
          method: 'GET'
          customHeaders: '{"Content-Type": "application/json", "Accept": "application/vnd.pagerduty+json;version=2", "Authorization": "Token token=${{ secrets.PAGERDUTY_API_KEY }}"}'
      - name: Extract Users From New Schedule
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        id: extract_users
        run: |
          USERS_JSON=$(echo '${{ steps.new_schedule.outputs.response }}' | jq -c '[.schedule.users[].summary]')
          echo "user_summaries=$USERS_JSON" >> $GITHUB_ENV
        shell: bash
  
      - name: Log Before Upserting Schedule to Port
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Ingesting updated schedule to Port..."
          
      - name: UPSERT Entity
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        uses: port-labs/port-github-action@v1
        with:
          identifier: "${{ fromJson(steps.new_schedule.outputs.response).schedule.id }}"
          title: "${{ fromJson(steps.new_schedule.outputs.response).schedule.name }}"
          blueprint: ${{fromJson(inputs.port_context).blueprint}}
          properties: |-
            {
              "url": "${{ fromJson(steps.new_schedule.outputs.response).schedule.html_url }}",
              "timezone": "${{ fromJson(steps.new_schedule.outputs.response).schedule.time_zone }}",
              "description": "${{ fromJson(steps.new_schedule.outputs.response).schedule.description}}",
              "users": ${{ env.user_summaries }}
            }
          relations: "{}"
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: UPSERT
          runId: ${{fromJson(inputs.port_context).run_id}}
      - name: Log After Upserting Entity
        if: steps.user_id_from_search.outputs.user_id != 'empty'
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Override created successfully โ
"
      - name: Log completion for user not found
        if: steps.user_id_from_search.outputs.user_id == 'empty'
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Action completed - user not found โ"
Add the self-service action
- 
Head to the self-service page. 
- 
Click on the + New Actionbutton.
- 
Click on the {...} Edit JSONbutton.
- 
Copy and paste the following JSON configuration: Change on-call user (click to expand){
 "identifier": "change_oncall_user",
 "title": "Change on-call user",
 "icon": "pagerduty",
 "description": "Create an override to change the current on-call user",
 "trigger": {
 "type": "self-service",
 "operation": "DAY-2",
 "userInputs": {
 "properties": {
 "new_on_call_user": {
 "icon": "User",
 "title": "New On-call User Email",
 "description": "Email address of the user who will be taking over the on-call duty",
 "type": "string",
 "format": "user"
 },
 "start_time": {
 "icon": "DefaultProperty",
 "title": "Start Time",
 "description": "Override start time (ISO 8601 format)",
 "type": "string",
 "format": "date-time"
 },
 "end_time": {
 "icon": "DefaultProperty",
 "title": "End Time",
 "description": "Override end time (ISO 8601 format)",
 "type": "string",
 "format": "date-time"
 }
 },
 "required": [
 "new_on_call_user",
 "start_time",
 "end_time"
 ],
 "order": [
 "new_on_call_user",
 "start_time",
 "end_time"
 ]
 },
 "blueprintIdentifier": "pagerdutySchedule"
 },
 "invocationMethod": {
 "type": "GITHUB",
 "org": "<GITHUB_ORG>",
 "repo": "<GITHUB_REPO>",
 "workflow": "change-oncall-user.yaml",
 "workflowInputs": {
 "start_time": "{{.inputs.\"start_time\"}}",
 "end_time": "{{.inputs.\"end_time\"}}",
 "new_on_call_user": "{{.inputs.\"new_on_call_user\"}}",
 "port_context": {
 "blueprint": "{{.action.blueprint}}",
 "entity": "{{.entity.identifier}}",
 "run_id": "{{.run.id}}"
 }
 },
 "reportWorkflowStatus": true
 },
 "requiredApproval": false
 }
- 
Click Save.
Delete schedule overrideโ
Remove an existing schedule override using a GitHub workflow.
GitHub workflow
Create the file .github/workflows/delete-schedule-override.yaml in the .github/workflows folder of your repository.
GitHub workflow script (click to expand)
name: Delete Schedule Override
on:
  workflow_dispatch:
    inputs:
      override_id:
        description: The ID of the override to delete
        required: true
        type: string
      port_context:
        required: true
        description: includes blueprint, run ID, and entity identifier from Port.
jobs:
  delete-schedule-override:
    runs-on: ubuntu-latest
    steps:
      - name: Inform start of override deletion
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Deleting schedule override... โด๏ธ"
      - name: Delete override from PagerDuty
        id: delete_override
        uses: fjogeleit/http-request-action@v1
        with:
          url: "https://api.pagerduty.com/schedules/${{fromJson(inputs.port_context).entity}}/overrides/${{ github.event.inputs.override_id }}"
          method: "DELETE"
          customHeaders: '{"Content-Type": "application/json", "Accept": "application/vnd.pagerduty+json;version=2", "Authorization": "Token token=${{ secrets.PAGERDUTY_API_KEY }}"}'
      - name: Log Before Requesting for Updated Schedule
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Getting updated schedule from PagerDuty..."
      - name: Request For Updated Schedule
        id: new_schedule
        uses: fjogeleit/http-request-action@v1
        with:
          url: 'https://api.pagerduty.com/schedules/${{fromJson(inputs.port_context).entity}}'
          method: 'GET'
          customHeaders: '{"Content-Type": "application/json", "Accept": "application/vnd.pagerduty+json;version=2", "Authorization": "Token token=${{ secrets.PAGERDUTY_API_KEY }}"}'
      - name: Extract Users From New Schedule
        id: extract_users
        run: |
          USERS_JSON=$(echo '${{ steps.new_schedule.outputs.response }}' | jq -c '[.schedule.users[].summary]')
          echo "user_summaries=$USERS_JSON" >> $GITHUB_ENV
        shell: bash
      - name: Log Before Upserting Schedule to Port
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Ingesting updated schedule to Port..."
      - name: UPSERT Entity
        uses: port-labs/port-github-action@v1
        with:
          identifier: "${{ fromJson(steps.new_schedule.outputs.response).schedule.id }}"
          title: "${{ fromJson(steps.new_schedule.outputs.response).schedule.name }}"
          blueprint: ${{fromJson(inputs.port_context).blueprint}}
          properties: |-
            {
              "url": "${{ fromJson(steps.new_schedule.outputs.response).schedule.html_url }}",
              "timezone": "${{ fromJson(steps.new_schedule.outputs.response).schedule.time_zone }}",
              "description": "${{ fromJson(steps.new_schedule.outputs.response).schedule.description}}",
              "users": ${{ env.user_summaries }}
            }
          relations: "{}"
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: UPSERT
          runId: ${{fromJson(inputs.port_context).run_id}}
      - name: Log completion
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{fromJson(inputs.port_context).run_id}}
          logMessage: "Schedule override deleted successfully โ
"
Add the self-service action
- 
Head to the self-service page. 
- 
Click on the + New Actionbutton.
- 
Click on the {...} Edit JSONbutton.
- 
Copy and paste the following JSON configuration: Delete schedule override (click to expand){
 "identifier": "delete_schedule_override",
 "title": "Delete schedule override",
 "icon": "pagerduty",
 "description": "Remove an existing schedule override",
 "trigger": {
 "type": "self-service",
 "operation": "DAY-2",
 "userInputs": {
 "properties": {
 "override_id": {
 "icon": "DefaultProperty",
 "title": "Override ID",
 "description": "The ID of the override to delete",
 "type": "string"
 }
 },
 "required": [
 "override_id"
 ],
 "order": [
 "override_id"
 ]
 },
 "blueprintIdentifier": "pagerdutySchedule"
 },
 "invocationMethod": {
 "type": "GITHUB",
 "org": "<GITHUB_ORG>",
 "repo": "<GITHUB_REPO>",
 "workflow": "delete-schedule-override.yaml",
 "workflowInputs": {
 "override_id": "{{.inputs.\"override_id\"}}",
 "port_context": {
 "blueprint": "{{.action.blueprint}}",
 "entity": "{{.entity.identifier}}",
 "run_id": "{{.run.id}}"
 }
 },
 "reportWorkflowStatus": true
 },
 "requiredApproval": false
 }
- 
Click Save.
Let's test it!โ
- 
Head to the self-service page of your portal 
- 
Test viewing current on-call user: - Navigate to a PagerDuty Schedule in your catalog.
- Click on View current on-call user.
- Click Execute.
- Review the response to see who is currently on-call.
 
- 
Test changing on-call user: - Navigate to a PagerDuty Schedule in your catalog.
- Click on Change on-call user.
- Fill in the required information:
- New On-call User Email: PagerDuty user email to assign.
- Start Time: When the override should begin.
- End Time: When the override should end.
 
- Click Execute.
 
- 
Test deleting schedule override: - Navigate to a PagerDuty Schedule in your catalog.
- Click on Delete schedule override.
- Fill in the Override ID of the override you want to remove.
- Click Execute.
 
Visualize metricsโ
With your on-call management actions in place and data flowing, we can create a dedicated dashboard in Port to visualize on-call coverage, schedules, and team assignments.
Create a dashboardโ
- 
Navigate to the Catalog page of your portal. 
- 
Click on the + Newbutton in the left sidebar.
- 
Select New dashboard. 
- 
Name the dashboard PagerDuty On-call Management. 
- 
Input Monitor and manage your PagerDuty on-call schedules and assignmentsunder Description.
- 
Select the PagerDutyicon.
- 
Click Create.
We now have a blank dashboard where we can start adding widgets to visualize insights from our PagerDuty on-call data.
Add widgetsโ
In the new dashboard, create the following widgets:
Total schedules count (click to expand)
- 
Click + Widgetand select Number Chart.
- 
Title: Total schedules
- 
Select Count entitiesChart type and choose PagerDuty Schedule as the Blueprint.
- 
Select countfor the Function.
- 
Select customas the Unit and inputschedulesas the Custom unit.
- 
Click Save.
Schedules created today (click to expand)
- 
Click + Widgetand select Number Chart.
- 
Title: Schedules created today.
- 
Select Count entitiesChart type and choose PagerDuty Schedule as the Blueprint.
- 
Select countfor the Function.
- 
Add this JSON to the Additional filters editor to filter schedules created today: [
 {
 "combinator": "and",
 "rules": [
 {
 "property": "$createdAt",
 "operator": "between",
 "value": {
 "preset": "today"
 }
 }
 ]
 }
 ]
- 
Select customas the Unit and inputschedulesas the Custom unit.
- 
Click Save.
Users by role (click to expand)
- 
Click + Widgetand select Pie chart.
- 
Title: Users by role.
- 
Choose the PagerDuty User blueprint. 
- 
Under Breakdown by property, select the Role property.
- 
Click Save.
Total users count (click to expand)
- 
Click + Widgetand select Number Chart.
- 
Title: Total users(add theUsericon).
- 
Select Count entitiesChart type and choose PagerDuty User as the Blueprint.
- 
Select countfor the Function.
- 
Select customas the Unit and inputusersas the Custom unit.
- 
Click Save.
All schedules table (click to expand)
- 
Click + Widgetand select Table.
- 
Title the widget All Schedules. 
- 
Choose the PagerDuty Schedule blueprint. 
- 
Click Saveto add the widget to the dashboard.
All users table (click to expand)
- 
Click + Widgetand select Table.
- 
Title the widget All Users. 
- 
Choose the PagerDuty User blueprint. 
- 
Click Saveto add the widget to the dashboard.
- 
Click on the ...button in the top right corner of the table and select Customize table.
- 
In the top right corner of the table, click on Manage Propertiesand add the following properties:- Email: User's email address.
- Role: User's role in PagerDuty.
- Time Zone: User's timezone.
- Created At: When the user account was created.
 
- 
Click on the save icon in the top right corner of the widget to save the customized table. 
On-call actions (click to expand)
- 
Click + Widgetand select Action card.
- 
Select View current on-call user, Change on-call user and Delete schedule override as the Actions. 
- 
Click Save.
Related guidesโ
- Change On-Call User: GitHub workflow for changing on-call assignments
- Create PagerDuty service: Create new PagerDuty services
- PagerDuty Integration: Complete setup guide for PagerDuty integration