Contract approval BPMN example
Contract approval is where a negotiated deal becomes a binding document, and it is usually the slowest week of the sales cycle. Legal reviews terms, finance checks the commercials, the customer redlines a clause, and the draft bounces between inboxes with no shared view of whose turn it is. Mapping the process gives every party the same answer to "where is the contract right now?".
The model uses a pool with Sales, Legal, and Commercial finance lanes, plus a second pool for the customer drawn as a black box: it holds no internal steps, because you cannot see or control the customer's signing process. Two message flows connect the pools, one carrying the contract out for signature and one bringing the signature back to a message catch event. That event, not a task, is what makes the wait explicit.
Standard BPMN 2.0 interchange XML: opens in Camunda Modeler, Signavio, Bizagi, and any other compliant tool.
The process at a glance
How to read this diagram
Work opens in the Sales lane when a contract is requested and a draft is prepared. Legal reviews the terms and answers the gateway "Redlines needed?": the Yes branch sends the draft back to Sales to negotiate revised terms, which loop into another legal review, while the default No branch moves the contract on to Commercial finance. There a second gateway asks "Commercial terms approved?", with the default No branch routing through a rework of the deal structure and back to finance.
Approval on both counts releases the send task, and a message flow carries the contract to the Customer pool for signature. The process then waits at the "Signature received" message catch event until the customer's message flow returns. Filing the signed contract closes the flow at "Contract executed" in the Sales lane. Both loops rejoin the main path, so however many revision rounds occur, every token still reaches that single end event.
BPMN elements used
| Element | Count | In this diagram |
|---|---|---|
| Start event | 1 | Contract requested |
| End event | 1 | Contract executed |
| Intermediate catch event | 1 | Signature received |
| Task | 3 | Prepare draft contract, Rework deal structure, File signed contract |
| User task | 3 | Review legal terms, Negotiate revised terms, Approve commercial terms |
| Send task | 1 | Send contract for signature |
| Exclusive gateway | 2 | Redlines needed?, Commercial terms approved? |
View the BPMN 2.0 XML for this diagram
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="swimdraft" exporterVersion="1.0">
<bpmn2:collaboration id="Collaboration_1">
<bpmn2:participant id="pool_ca" name="Contract approval" processRef="Process_pool_ca" />
<bpmn2:participant id="pool_ca_customer" name="Customer" processRef="Process_pool_ca_customer" />
<bpmn2:messageFlow id="mca1" name="Contract for signature" sourceRef="t_ca_send" targetRef="pool_ca_customer" />
<bpmn2:messageFlow id="mca2" name="Signed contract" sourceRef="pool_ca_customer" targetRef="ev_ca_signed" />
</bpmn2:collaboration>
<bpmn2:process id="Process_pool_ca" isExecutable="false">
<bpmn2:laneSet id="LaneSet_pool_ca">
<bpmn2:lane id="lane_ca_sales" name="Sales">
<bpmn2:flowNodeRef>start_ca</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_ca_draft</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_ca_negotiate</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_ca_rework</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_ca_send</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>ev_ca_signed</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>t_ca_file</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>end_ca_done</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_ca_legal" name="Legal">
<bpmn2:flowNodeRef>t_ca_legal</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>g_ca_redline</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_ca_fin" name="Commercial finance">
<bpmn2:flowNodeRef>t_ca_fin</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>g_ca_approve</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="start_ca" name="Contract requested">
<bpmn2:outgoing>fca1</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:task id="t_ca_draft" name="Prepare draft contract">
<bpmn2:incoming>fca1</bpmn2:incoming>
<bpmn2:outgoing>fca2</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:userTask id="t_ca_legal" name="Review legal terms">
<bpmn2:incoming>fca2</bpmn2:incoming>
<bpmn2:incoming>fca6</bpmn2:incoming>
<bpmn2:outgoing>fca3</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:exclusiveGateway id="g_ca_redline" name="Redlines needed?" default="fca5">
<bpmn2:incoming>fca3</bpmn2:incoming>
<bpmn2:outgoing>fca4</bpmn2:outgoing>
<bpmn2:outgoing>fca5</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:userTask id="t_ca_negotiate" name="Negotiate revised terms">
<bpmn2:incoming>fca4</bpmn2:incoming>
<bpmn2:outgoing>fca6</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:userTask id="t_ca_fin" name="Approve commercial terms">
<bpmn2:incoming>fca5</bpmn2:incoming>
<bpmn2:incoming>fca10</bpmn2:incoming>
<bpmn2:outgoing>fca7</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:exclusiveGateway id="g_ca_approve" name="Commercial terms approved?" default="fca9">
<bpmn2:incoming>fca7</bpmn2:incoming>
<bpmn2:outgoing>fca8</bpmn2:outgoing>
<bpmn2:outgoing>fca9</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:task id="t_ca_rework" name="Rework deal structure">
<bpmn2:incoming>fca9</bpmn2:incoming>
<bpmn2:outgoing>fca10</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sendTask id="t_ca_send" name="Send contract for signature">
<bpmn2:incoming>fca8</bpmn2:incoming>
<bpmn2:outgoing>fca11</bpmn2:outgoing>
</bpmn2:sendTask>
<bpmn2:intermediateCatchEvent id="ev_ca_signed" name="Signature received">
<bpmn2:incoming>fca11</bpmn2:incoming>
<bpmn2:outgoing>fca12</bpmn2:outgoing>
<bpmn2:messageEventDefinition id="ev_ca_signed_def" />
</bpmn2:intermediateCatchEvent>
<bpmn2:task id="t_ca_file" name="File signed contract">
<bpmn2:incoming>fca12</bpmn2:incoming>
<bpmn2:outgoing>fca13</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:endEvent id="end_ca_done" name="Contract executed">
<bpmn2:incoming>fca13</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="fca1" sourceRef="start_ca" targetRef="t_ca_draft" />
<bpmn2:sequenceFlow id="fca2" sourceRef="t_ca_draft" targetRef="t_ca_legal" />
<bpmn2:sequenceFlow id="fca3" sourceRef="t_ca_legal" targetRef="g_ca_redline" />
<bpmn2:sequenceFlow id="fca4" name="Yes" sourceRef="g_ca_redline" targetRef="t_ca_negotiate">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="fca5" name="No" sourceRef="g_ca_redline" targetRef="t_ca_fin" />
<bpmn2:sequenceFlow id="fca6" sourceRef="t_ca_negotiate" targetRef="t_ca_legal" />
<bpmn2:sequenceFlow id="fca7" sourceRef="t_ca_fin" targetRef="g_ca_approve" />
<bpmn2:sequenceFlow id="fca8" name="Yes" sourceRef="g_ca_approve" targetRef="t_ca_send">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="fca9" name="No" sourceRef="g_ca_approve" targetRef="t_ca_rework" />
<bpmn2:sequenceFlow id="fca10" sourceRef="t_ca_rework" targetRef="t_ca_fin" />
<bpmn2:sequenceFlow id="fca11" sourceRef="t_ca_send" targetRef="ev_ca_signed" />
<bpmn2:sequenceFlow id="fca12" sourceRef="ev_ca_signed" targetRef="t_ca_file" />
<bpmn2:sequenceFlow id="fca13" sourceRef="t_ca_file" targetRef="end_ca_done" />
</bpmn2:process>
<bpmn2:process id="Process_pool_ca_customer" isExecutable="false">
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
<bpmndi:BPMNShape id="pool_ca_di" bpmnElement="pool_ca" isHorizontal="true">
<dc:Bounds x="20" y="20" width="1570" height="500" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_ca_sales_di" bpmnElement="lane_ca_sales" isHorizontal="true">
<dc:Bounds x="50" y="20" width="1540" height="240" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_ca_legal_di" bpmnElement="lane_ca_legal" isHorizontal="true">
<dc:Bounds x="50" y="260" width="1540" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="lane_ca_fin_di" bpmnElement="lane_ca_fin" isHorizontal="true">
<dc:Bounds x="50" y="390" width="1540" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="pool_ca_customer_di" bpmnElement="pool_ca_customer" isHorizontal="true">
<dc:Bounds x="20" y="580" width="1570" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="start_ca_di" bpmnElement="start_ca">
<dc:Bounds x="112" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="82" y="101" width="96" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_draft_di" bpmnElement="t_ca_draft">
<dc:Bounds x="230" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_legal_di" bpmnElement="t_ca_legal">
<dc:Bounds x="380" y="277" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="g_ca_redline_di" bpmnElement="g_ca_redline">
<dc:Bounds x="555" y="292" width="50" height="50" />
<bpmndi:BPMNLabel><dc:Bounds x="535" y="272" width="91" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_negotiate_di" bpmnElement="t_ca_negotiate">
<dc:Bounds x="680" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_fin_di" bpmnElement="t_ca_fin">
<dc:Bounds x="680" y="407" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="g_ca_approve_di" bpmnElement="g_ca_approve">
<dc:Bounds x="855" y="422" width="50" height="50" />
<bpmndi:BPMNLabel><dc:Bounds x="834" y="478" width="92" height="28" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_rework_di" bpmnElement="t_ca_rework">
<dc:Bounds x="980" y="147" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_send_di" bpmnElement="t_ca_send">
<dc:Bounds x="980" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="ev_ca_signed_di" bpmnElement="ev_ca_signed">
<dc:Bounds x="1162" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="1133" y="101" width="94" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="t_ca_file_di" bpmnElement="t_ca_file">
<dc:Bounds x="1280" y="37" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_ca_done_di" bpmnElement="end_ca_done">
<dc:Bounds x="1462" y="59" width="36" height="36" />
<bpmndi:BPMNLabel><dc:Bounds x="1434" y="101" width="92" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="fca1_di" bpmnElement="fca1">
<di:waypoint x="148" y="77" />
<di:waypoint x="230" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca2_di" bpmnElement="fca2">
<di:waypoint x="330" y="77" />
<di:waypoint x="360" y="77" />
<di:waypoint x="360" y="317" />
<di:waypoint x="380" y="317" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca3_di" bpmnElement="fca3">
<di:waypoint x="480" y="317" />
<di:waypoint x="555" y="317" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca4_di" bpmnElement="fca4">
<di:waypoint x="605" y="317" />
<di:waypoint x="660" y="317" />
<di:waypoint x="660" y="77" />
<di:waypoint x="680" y="77" />
<bpmndi:BPMNLabel><dc:Bounds x="611" y="297" width="21" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca5_di" bpmnElement="fca5">
<di:waypoint x="605" y="317" />
<di:waypoint x="660" y="317" />
<di:waypoint x="660" y="447" />
<di:waypoint x="680" y="447" />
<bpmndi:BPMNLabel><dc:Bounds x="611" y="323" width="17" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca6_di" bpmnElement="fca6">
<di:waypoint x="780" y="77" />
<di:waypoint x="810" y="77" />
<di:waypoint x="810" y="132" />
<di:waypoint x="360" y="132" />
<di:waypoint x="360" y="317" />
<di:waypoint x="380" y="317" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca7_di" bpmnElement="fca7">
<di:waypoint x="780" y="447" />
<di:waypoint x="855" y="447" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca8_di" bpmnElement="fca8">
<di:waypoint x="905" y="447" />
<di:waypoint x="960" y="447" />
<di:waypoint x="960" y="77" />
<di:waypoint x="980" y="77" />
<bpmndi:BPMNLabel><dc:Bounds x="911" y="427" width="21" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca9_di" bpmnElement="fca9">
<di:waypoint x="905" y="447" />
<di:waypoint x="960" y="447" />
<di:waypoint x="960" y="187" />
<di:waypoint x="980" y="187" />
<bpmndi:BPMNLabel><dc:Bounds x="911" y="453" width="17" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca10_di" bpmnElement="fca10">
<di:waypoint x="1080" y="187" />
<di:waypoint x="1110" y="187" />
<di:waypoint x="1110" y="242" />
<di:waypoint x="660" y="242" />
<di:waypoint x="660" y="447" />
<di:waypoint x="680" y="447" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca11_di" bpmnElement="fca11">
<di:waypoint x="1080" y="77" />
<di:waypoint x="1162" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca12_di" bpmnElement="fca12">
<di:waypoint x="1198" y="77" />
<di:waypoint x="1280" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="fca13_di" bpmnElement="fca13">
<di:waypoint x="1380" y="77" />
<di:waypoint x="1462" y="77" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="mca1_di" bpmnElement="mca1">
<di:waypoint x="1080" y="77" />
<di:waypoint x="1110" y="77" />
<di:waypoint x="1110" y="550" />
<di:waypoint x="1110" y="580" />
<bpmndi:BPMNLabel><dc:Bounds x="1116" y="543" width="108" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="mca2_di" bpmnElement="mca2">
<di:waypoint x="1110" y="580" />
<di:waypoint x="1110" y="550" />
<di:waypoint x="1110" y="77" />
<di:waypoint x="1162" y="77" />
<bpmndi:BPMNLabel><dc:Bounds x="1025" y="543" width="79" height="14" /></bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>Frequently asked questions
Why is the customer a black box pool with no tasks inside?
You can only model behaviour you can see and govern. The customer's internal signing steps are unknown, so BPMN convention draws them as an empty pool and shows just the message exchange: contract out, signature back. If you later integrate an e-signature platform, you might model that platform's callbacks instead.
Why do the message flows connect to a send task and a catch event rather than the pool border only?
Anchoring message flows to the specific send task and message catch event shows exactly where in the flow the exchange happens, which matters when the process pauses. The catch event is the pause: the token sits there until the signature message arrives. A plain task would hide that waiting semantics.
Could the two approval loops be combined into one gateway?
Only by losing information. Legal redlines and commercial approval are different questions answered by different lanes with different rework paths: one renegotiates wording, the other restructures the deal. Separate exclusive gateways keep each decision owner visible. Combining them would need a shared rework task that muddles accountability.
Related BPMN examples
Lead qualification
A lead qualification process as a BPMN 2.0 diagram: scoring, discovery, and handover to sales. View the swimlane diagram and download the .bpmn file free.
Quote approval
A quote approval workflow as a BPMN 2.0 diagram: pricing rules, discount escalation to finance, and a rework loop. See the diagram and download the .bpmn file free.
Sales order processing
Sales order processing as a BPMN 2.0 diagram: stock check, back order timer loop, parallel picking and invoicing. View it and download the .bpmn file free.
Customer onboarding
A customer onboarding process as a BPMN 2.0 diagram: kickoff, parallel provisioning and billing setup, go live checklist. Download the .bpmn file free.
Generate your own version of this diagram
Describe how the process works in your organisation: plain English, meeting notes, a transcript, or a spreadsheet. Swimdraft turns it into a spec-validated BPMN 2.0 diagram you can edit in the browser and export as .bpmn, SVG, or PNG.
Start freeNo credit card required