Contracts API

Contracts API Reference

Create and manage multi-party smart contracts with automatic execution, escrow functionality, and milestone-based payments. Perfect for service agreements, freelance contracts, and business deals.

Overview

The Contracts API enables you to create sophisticated multi-party agreements with built-in payment processing, milestone tracking, and automated execution. Each contract can have multiple parties with different roles and payment responsibilities.

Multi-Party

Support for unlimited parties with customizable roles and permissions

Milestones

Break contracts into milestones with conditional payments

Automation

Automatic execution based on conditions and approvals

POSTCreate Contract

Create a new complex contract that can contain multiple milestones

Endpoint

POST /api/external/contracts

Request Body

{
  "type": "COMPLEX_CONTRACT",
  "senderRole": "BROKER",
  "itemDetail": {
    "title": "example title",
    "description": "example description",
    "images": [
      "image url1",
      "image url2"
    ]
  },
  "returnPolicy": "NO_RETURN",
  "returnFeePayee": "PROVIDER",
  "waffyTermsAccepted": true,
  "category": "Services"
}

Sender Role Values

PROVIDER,CUSTOMER,BROKER

Response (201 Created)

{
  "status": 201,
  "timestamp": "2026-01-21T17:00:01.408195",
  "data": {
    "id": "6971061074385b2c31672af3",
    "version": 0,
    "shortId": "UEVlKJpT",
    "type": "COMPLEX_CONTRACT",
    "senderId": "12345678",
    "senderRole": "BROKER",
    "itemDetail": {
      "title": "example title",
      "description": "example description",
      "images": [
        "image url1",
        "image url2"
      ]
    },
    "itemPrice": 0.0,
    "totalAmount": 0.0,
    "currency": null,
    "status": "CREATED",
    "createdAt": "2026-01-21T17:00:00.724+00:00",
    "contractClassification": "BASIC",
    "isParent": true,
    "parties": [
      {
        "userId": "12345678",
        "role": "BROKER",
        "phoneNumber": "+966559555555",
        "isSender": true,
        "arbitrator": true
      }
    ],
    "category": "Services",
    "organization": {
      "organizationCode": "merchant_organization_code",
      "accountId": 1234
    }
  }
}

PATCHAdd Milestones

Add milestone sub-contracts to the main contract

Endpoint

PATCH /api/external/contracts/6971061074385b2c31672af3/milestones
Note:The contract ID in the URL parameter is the parent complex contract ID returned from the "Create Contract" API.

Request Body

{
  "milestones": [
    {
      "type": "MILESTONE_CONTRACT",
      "senderRole": "PROVIDER",
      "itemDetail": {
        "title": "first milestone example title",
        "description": "first milestone example description"
      },
      "itemPrice": 100000,
      "currency": "SAR",
      "returnPolicy": "NO_RETURN",
      "returnFeePayee": "PROVIDER",
      "deadLine": "2024-10-28T10:34:57.536Z",
      "waffyTermsAccepted": true,
      "addOnFees": [
        {
          "amount": 10,
          "description": "Extra 10% Amount",
          "beneficiary": "+966559555555",
          "payee": "+966555444444",
          "type": "EXTRA_AMOUNT",
          "feeType": "FLAT"
        }
      ]
    }
  ]
}

AddOn Fee Types

SHIPPING_FEES,SERVICE_FEES,EXTRA_AMOUNT,PLATFORM_COMMISSION,PAYMENT_FEES

Response (200 OK)

{
  "status": 200,
  "timestamp": "2026-01-21T17:07:02.599251",
  "data": {
    "parentContractId": "6971061074385b2c31672af3",
    "milestones": [
      {
        "id": "697107b674385b2c31672af5",
        "shortId": "pUZB9kCK",
        "type": "MILESTONE_CONTRACT",
        "senderRole": "BROKER",
        "receiverRole": "CUSTOMER",
        "itemDetail": {
          "title": "first milestone example title",
          "description": "first milestone example description"
        },
        "itemPrice": 100000.0,
        "fee": 4000.0,
        "feePercentage": 0.04,
        "totalAmount": 104000.0,
        "currency": "SAR",
        "status": "CREATED",
        "isParent": false,
        "parentId": "6971061074385b2c31672af3",
        "deadLine": "2024-10-28T10:34:57.536+00:00",
        "addonFeesList": [
          {
            "amount": 10.0,
            "feeType": "FLAT",
            "description": "Extra 10% Amount",
            "beneficiary": "+966559555555",
            "payee": "+966555444444",
            "type": "EXTRA_AMOUNT"
          }
        ]
      }
    ]
  }
}

PATCHAdd Parties

Add parties to milestone contracts with roles and amounts

Endpoint

PATCH /api/external/contracts/6971061074385b2c31672af3/parties
Note:The contract ID in the URL is the parent contract created in the first request. The map keys in the request body (e.g., "697107b674385b2c31672af5") are the milestone IDs created in the "Add Milestones" API.

Request Body

{
  "mileStonesParties": {
    "697107b674385b2c31672af5": [
      {
        "phoneNumber": "+966555444444",
        "role": "CUSTOMER",
        "amount": 100000
      },
      {
        "phoneNumber": "+966559555555",
        "role": "BROKER",
        "amount": 99100,
        "arbitrator": true
      },
      {
        "phoneNumber": "+966555444445",
        "role": "PROVIDER",
        "amount": 910,
        "isSender": true
      }
    ]
  }
}

Response (200 OK)

{
  "status": 200,
  "timestamp": "2026-01-21T17:12:02.474103",
  "data": {
    "id": "6971061074385b2c31672af3",
    "type": "COMPLEX_CONTRACT",
    "status": "CREATED",
    "parties": [
      {
        "userId": "12345678",
        "role": "BROKER",
        "phoneNumber": "+966559555555",
        "amount": 99100,
        "arbitrator": true
      },
      {
        "userId": "23456789",
        "role": "CUSTOMER",
        "phoneNumber": "+966555444444",
        "amount": 100000
      },
      {
        "userId": "34567891",
        "role": "PROVIDER",
        "phoneNumber": "+966555444445",
        "amount": 910,
        "isSender": true
      }
    ],
    "isAcceptable": true
  }
}

GETGet Contract

Retrieve contract details and current status

Endpoint

GET/api/contracts/{contract_id}
Note:If the ID of a parent "complex" contract is specified, the info of that contract only (without milestones) will be returned. To get milestone details, use the milestone ID directly or use the "Get Contract Milestones" API.

Response (200 OK)

{
  "status": 200,
  "timestamp": "2026-01-25T11:19:00.872608",
  "data": {
    "id": "6971061074385b2c31672af3",
    "version": 1,
    "shortId": "UEVlKJpT",
    "type": "COMPLEX_CONTRACT",
    "senderId": "12345678",
    "senderPhoneNumber": null,
    "senderRole": "BROKER",
    "receiverId": null,
    "receiverPhoneNumber": null,
    "receiverRole": null,
    "provider": null,
    "customer": null,
    "itemDetail": {
      "title": "test contract",
      "description": "test description",
      "fields": null,
      "images": [
        "image url example"
      ],
      "attachments": []
    },
    "itemPrice": 0.0,
    "unitPrice": null,
    "quantity": null,
    "originalQuantity": 0,
    "fee": 0.0,
    "feePercentage": 0.0,
    "totalAmount": 0.0,
    "currency": null,
    "feePayee": "PROVIDER",
    "status": "CREATED",
    "createdAt": "2026-01-21T17:00:00.724+00:00",
    "updatedAt": "2026-01-21T17:12:02.769+00:00",
    "clientReferenceId": null,
    "contractClassification": "BASIC",
    "isParent": true,
    "parentId": null,
    "brokerFee": 0.0,
    "parties": [
      {
        "userId": "23456789",
        "role": "PROVIDER",
        "phoneNumber": "+966555444445",
        "sudoRole": null,
        "sudoName": null,
        "isSender": true,
        "amount": 910.0,
        "fee": 36.4,
        "feeType": null,
        "feePercentage": 0.04,
        "status": "JOINED",
        "arbitrator": false,
        "credited": false,
        "invitationId": null,
        "rejectionReason": null
      },
      {
        "userId": "12345678",
        "role": "BROKER",
        "phoneNumber": "+966559555555",
        "sudoRole": null,
        "sudoName": null,
        "isSender": true,
        "amount": 99100.0,
        "fee": 3964.0,
        "feeType": null,
        "feePercentage": 0.04,
        "status": "JOINED",
        "arbitrator": true,
        "credited": false,
        "invitationId": null,
        "rejectionReason": null
      }
    ],
    "partiesProfiles": {
      "PROVIDER": [
        {
          "id": 1234,
          "userIdentification": 23456789,
          "phoneNumber": "+966555444445",
          "nationalIdVerified": false,
          "profile": {
            "firstName": "test",
            "lastName": "user",
            "fullName": "test user"
          }
        }
      ],
      "BROKER": [
        {
          "id": 2345,
          "userIdentification": 12345678,
          "phoneNumber": "+966559555555",
          "nationalIdVerified": false,
          "profile": {
            "firstName": "test",
            "lastName": "user2",
            "fullName": "test user2"
          }
        }
      ]
    },
    "deadLine": null,
    "metaData": null,
    "category": "Services",
    "transactions": [],
    "addonFeesList": [],
    "shipment": {
      "number": null,
      "type": null,
      "shipmentCompany": null,
      "provider": null,
      "fee": 0.0,
      "currency": null,
      "feePayee": null,
      "info": null,
      "shipmentRequestId": null,
      "bookingId": null,
      "stickerUrl": null,
      "createdAt": "2026-01-21T16:59:57.809+00:00"
    },
    "returnShipment": null,
    "addressesMap": null,
    "acceptanceConditions": null,
    "cancellationConditions": null,
    "activeChildrenCount": 1,
    "activeChildrenTotalAmount": 100000.0,
    "activeChildrenPartiesCount": 3,
    "isInspectable": false,
    "isAcceptable": true,
    "paymentMethods": null,
    "currentStep": null,
    "operationsMetaData": null,
    "organization": {
      "organizationCode": "merchant_organization_code",
      "accountId": 2384
    },
    "originalItemPrice": null,
    "deliveryInDays": 5,
    "deliveryInMinutes": 0,
    "returnPolicy": null,
    "inspectionPeriod": 2,
    "returnFee": 0.0,
    "returnFeePayee": null,
    "returnItem": null,
    "waffyTermsAccepted": false,
    "escalations": [],
    "reminders": [],
    "uncompletedActions": [],
    "customerAdditionalInfo": null,
    "customerShippingAddress": null,
    "organizationCode": "merchant_organization_code",
    "contractDefinitionId": null,
    "redemptionId": null,
    "isPrivate": null,
    "feePercentageMap": null,
    "address": null,
    "deliveryNotes": null,
    "cashOutAmountList": null,
    "waffyExtraFees": [],
    "cashOutAttachments": null,
    "cashOutComment": null,
    "settlementActorId": null,
    "settledAt": null,
    "cashOutParticipantAmountMap": null,
    "invoices": [],
    "settlementOut": false,
    "finalItemPrice": 0.0,
    "deservedFees": 0.0,
    "settled": false,
    "hasVoucher": false,
    "shippable": false
  }
}

GETGet Contract Milestones

Retrieve milestones for a parent contract with pagination

Endpoint

GET /api/contracts?parentId={parent_contract_id}&sort=createdAt%2CASC
Note:The contract ID is the parent "complex" contract that we need to query its milestones.

Response (200 OK)

{
  "status": 200,
  "timestamp": "2026-01-25T11:21:45.578018",
  "data": {
    "content": [
      {
        "id": "697107b674385b2c31672af5",
        "version": 4,
        "shortId": "pUZB9kCK",
        "type": "MILESTONE_CONTRACT",
        "senderId": "12345678",
        "senderRole": "BROKER",
        "receiverRole": "CUSTOMER",
        "itemDetail": {
          "title": "دفعة اوي",
          "description": "",
          "fields": null,
          "images": null,
          "attachments": null
        },
        "itemPrice": 100000.0,
        "fee": 4000.0,
        "feePercentage": 0.04,
        "totalAmount": 104000.0,
        "currency": "SAR",
        "feePayee": "PROVIDER",
        "status": "CREATED",
        "createdAt": "2026-01-21T17:07:02.545+00:00",
        "updatedAt": "2026-01-21T17:12:02.912+00:00",
        "contractClassification": "BASIC",
        "isParent": false,
        "parentId": "6971061074385b2c31672af3",
        "brokerFee": 0.0,
        "parties": [
          {
            "userId": "23456789",
            "role": "CUSTOMER",
            "phoneNumber": "+966555444444",
            "sudoRole": null,
            "sudoName": null,
            "isSender": false,
            "amount": 100000.0,
            "fee": 4000.0,
            "feeType": null,
            "feePercentage": 0.04,
            "status": "JOINED",
            "arbitrator": false,
            "credited": false,
            "invitationId": null,
            "rejectionReason": null
          },
          {
            "userId": "12345678",
            "role": "BROKER",
            "phoneNumber": "+966559555555",
            "sudoRole": null,
            "sudoName": null,
            "isSender": true,
            "amount": 99100.0,
            "fee": 3964.0,
            "feeType": null,
            "feePercentage": 0.04,
            "status": "JOINED",
            "arbitrator": true,
            "credited": false,
            "invitationId": null,
            "rejectionReason": null
          },
          {
            "userId": "34567891",
            "role": "PROVIDER",
            "phoneNumber": "+966555444445",
            "sudoRole": null,
            "sudoName": null,
            "isSender": true,
            "amount": 910.0,
            "fee": 36.4,
            "feeType": null,
            "feePercentage": 0.04,
            "status": "JOINED",
            "arbitrator": false,
            "credited": false,
            "invitationId": null,
            "rejectionReason": null
          }
        ],
        "partiesProfiles": {
          "CUSTOMER": [
            {
              "id": 2224,
              "userIdentification": 23456789,
              "phoneNumber": "+966555444444",
              "nationalIdVerified": false,
              "profile": {
                "firstName": "test",
                "lastName": "user",
                "fullName": "test user"
              }
            }
          ],
          "BROKER": [
            {
              "id": 2178,
              "userIdentification": 12345678,
              "phoneNumber": "+966559555555",
              "nationalIdVerified": false,
              "profile": {
                "firstName": "test",
                "lastName": "",
                "fullName": "test "
              }
            }
          ],
          "PROVIDER": [
            {
              "id": 2223,
              "userIdentification": 34567891,
              "phoneNumber": "+966555444445",
              "nationalIdVerified": false,
              "profile": {
                "firstName": "test",
                "lastName": "user",
                "fullName": "test user"
              }
            }
          ]
        },
        "deadLine": "2024-10-28T10:34:57.536+00:00",
        "metaData": null,
        "category": null,
        "transactions": [],
        "addonFeesList": [
          {
            "amount": 10.0,
            "feeType": "FLAT",
            "description": "Extra 10% Amount",
            "beneficiary": "+966559555555",
            "payee": "+966555444444",
            "type": "EXTRA_AMOUNT"
          }
        ],
        "shipment": {
          "number": null,
          "type": null,
          "shipmentCompany": null,
          "provider": null,
          "fee": 0.0,
          "currency": null,
          "feePayee": null,
          "info": null,
          "shipmentRequestId": null,
          "bookingId": null,
          "stickerUrl": null,
          "createdAt": "2026-01-21T17:07:00.657+00:00"
        },
        "returnShipment": null,
        "addressesMap": null,
        "acceptanceConditions": null,
        "cancellationConditions": null,
        "activeChildrenCount": null,
        "activeChildrenTotalAmount": null,
        "activeChildrenPartiesCount": null,
        "isInspectable": false,
        "isAcceptable": true,
        "paymentMethods": null,
        "currentStep": null,
        "operationsMetaData": null,
        "organization": {
          "organizationCode": "merchant_organization_code",
          "accountId": 2384
        },
        "originalItemPrice": null,
        "deliveryInDays": 5,
        "deliveryInMinutes": 0,
        "returnPolicy": null,
        "inspectionPeriod": 2,
        "returnFee": 0.0,
        "returnFeePayee": null,
        "returnItem": null,
        "waffyTermsAccepted": false,
        "escalations": [],
        "reminders": [],
        "uncompletedActions": [],
        "customerAdditionalInfo": null,
        "customerShippingAddress": null,
        "organizationCode": "merchant_organization_code",
        "contractDefinitionId": null,
        "redemptionId": null,
        "isPrivate": null,
        "feePercentageMap": {
          "normalFee": 0.04,
          "tabbyFee": 0.055
        },
        "address": null,
        "deliveryNotes": null,
        "cashOutAmountList": null,
        "waffyExtraFees": [],
        "cashOutAttachments": null,
        "cashOutComment": null,
        "settlementActorId": null,
        "settledAt": null,
        "cashOutParticipantAmountMap": null,
        "invoices": [],
        "settlementOut": false,
        "finalItemPrice": 100000.0,
        "deservedFees": 4000.0,
        "settled": false,
        "hasVoucher": false,
        "shippable": false
      }
    ],
    "pageable": {
      "sort": {
        "empty": false,
        "sorted": true,
        "unsorted": false
      },
      "offset": 0,
      "pageNumber": 0,
      "pageSize": 10,
      "paged": true,
      "unpaged": false
    },
    "totalElements": 1,
    "totalPages": 1,
    "last": true,
    "sort": {
      "empty": false,
      "sorted": true,
      "unsorted": false
    },
    "size": 10,
    "number": 0,
    "numberOfElements": 1,
    "first": true,
    "empty": false
  }
}

GETList Contracts

Retrieve a list of contracts with filtering options

Endpoint

GET/api/contracts

Query Parameters

ParameterTypeDescription
statusstringFilter by status: pending_signatures, active, completed, cancelled
user_idstringFilter by user involved in contract
limitintegerNumber of results to return (max 100, default 20)
offsetintegerNumber of results to skip (for pagination)

Contract Statuses

Understanding the contract lifecycle

pending_signatures
Waiting for all parties to sign the contract
active
Contract is active and milestones are being executed
completed
All milestones completed and payments processed
cancelled
Contract was cancelled, funds returned to appropriate parties

Common Errors

400 Bad Request - Invalid Party

{
  "success": false,
  "error": {
    "code": "INVALID_PARTY",
    "message": "User usr_invalid123 is not a valid Waffy user",
    "details": {
      "user_id": "usr_invalid123"
    }
  }
}

409 Conflict - Milestone Already Completed

{
  "success": false,
  "error": {
    "code": "MILESTONE_ALREADY_COMPLETED",
    "message": "Milestone mls_1a2b3c4d has already been completed",
    "details": {
      "milestone_id": "mls_1a2b3c4d",
      "completed_at": "2024-01-20T15:30:00Z"
    }
  }
}

Contract Templates

Use pre-built templates for common contract types

Webhooks Integration

Get real-time notifications for contract events