Python Power Automate - Approvals

Approval flows started from services, with outcomes received synchronously or through callbacks.

Approvals are one of the most popular uses of Power Automate - a document, a purchase, or a request goes to a person who approves or rejects it in Teams, Outlook or the Power Automate portal. Your Python services fit in on both sides: they start approval flows, and they receive the outcomes.

The pattern is a flow with an HTTP request trigger, followed by a "Start and wait for an approval" action, followed by actions that report the outcome back - either through a synchronous Response action or by calling a Zato REST channel.

Starting an approval

The service triggers the flow with everything the approver needs to see. You create the flow once in Power Automate, and the connection does the rest.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class RequestPurchaseApproval(Service):

    input = 'requester', 'item', 'amount'

    def handle(self):

        # Get the connection by its Dashboard name
        conn = self.microsoft.power_platform['My Power Automate']

        # Start the approval flow with the details the approver will see
        conn.trigger('flow-purchase-approval', {
            'requester': self.request.input.requester,
            'item': self.request.input.item,
            'amount': self.request.input.amount,
        })

        self.response.payload = {'status': 'approval-requested'}

Waiting for the outcome synchronously

For approvals that resolve quickly - or when the caller can wait - end the flow with a Response action after the approval action, and the outcome comes back as the trigger's response.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class RequestDiscountApproval(Service):

    input = 'customer_id', 'discount_percent'

    def handle(self):

        conn = self.microsoft.power_platform['My Power Automate']

        # The flow waits for the approval and responds with its outcome
        result = conn.trigger('flow-discount-approval', {
            'customer_id': self.request.input.customer_id,
            'discount_percent': self.request.input.discount_percent,
        })

        # The Response action of the flow returns the approval outcome
        self.response.payload = {'outcome': result['outcome']}

Receiving the outcome asynchronously

Most approvals take hours or days, so the usual design is fire-and-forget plus a callback. The flow's final action is an HTTP call to a Zato REST channel, and the service below is what the channel points to.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class OnApprovalOutcome(Service):
    """ Invoked by the approval flow through a REST channel once the approver decides.
    """
    input = 'item', 'outcome', 'approver'

    def handle(self):

        item = self.request.input.item
        outcome = self.request.input.outcome
        approver = self.request.input.approver

        self.logger.info('Approval for %s: %s (by %s)', item, outcome, approver)

        # React to the decision - update the ERP, notify the requester, and so on
        if outcome == 'Approve':
            self.invoke('purchase.create-order', {'item': item})

Keeping an eye on pending approvals

Approval flows show up in the run history like any other flow - a run whose status is Running is an approval still waiting for a decision. See monitoring runs for the details, including cancelling approvals that are no longer relevant.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class CountPendingApprovals(Service):

    def handle(self):

        conn = self.microsoft.power_platform['My Power Automate']

        response = conn.list_runs('flow-purchase-approval')

        # Runs still executing are approvals awaiting a decision
        pending = 0
        for run in response['value']:
            if run['properties']['status'] == 'Running':
                pending += 1

        self.response.payload = {'pending': pending}

More resources

Learn more