Skip to main content

CreateDispute

Step 1: Create dispute​

User can create dispute for a contract by providing the requester's id, contract id and reason for dispute.

Implementation Examples​

POST {{BaseUrl}}/apps/api/disputes

Headers:

  • Authorization: Bearer {access_token} — Replace {access_token} with the token obtained from Step 1.
  • Content-Type: application/json
{
"requesterPlatformRefId": "USR_01KZ15DDR0KN",
"externalContractId": "CNT-000000GFZ000",
"reason": "OtherDisputeReason",
"otherMessage": "some text to explain the dispute",
"suggestions": "explain the suggestions",
"attachmentsIds": ["ATT-000000GFZ000", "ATT-000000GFZ001"]
}

Field Descriptions​

Field NameTypeDescriptionRequired / Notes / Example
requesterPlatformRefIdstringRequester's platform reference IDRequired
externalContractIdstringExternal contract IDRequired
reasonstringReason for disputeRequired
otherMessagestringAdditional message for disputeOptional
suggestionsstringSuggestions for dispute resolutionOptional
attachmentsIdsarrayList of attachments Ids to proof user's claimRequired

Example Request (cURL)​

curl --location '{{BaseUrl}}/apps/api/dispute' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YourTokenGoesHere' \
--data '{
"externalContractId": "CNT-01KX12PR976YD7FFKRWNQ58DQT",
"reason": "ProductNotGood",
"suggestions": "Suggestions",
"attachmentsIds": ["ATT-000000GFZ000"],

}'

Example Response​

{
"data": {
"disputeId": 1
},
"message": "Dispute created and contract status updated successfully.",
"status": 200,
"errorCode": null,
"validationErrors": []
}

Reasons options​

public enum DisputeReasons
{
ProductNotGood = 1,
ServiceNotMatchingRequirements = 2,
DeliveryIssue = 3,
PaymentIssue = 4,
ContractViolation = 5,
DamagedProduct = 6,
ServiceIncomplete = 7,
OtherDisputeReason = 99
}

Webhooks sent when a dispute is created​

Creating a dispute sends two webhooks: dispute.created, and a status webhook. The status webhook is milestone.disputed when the contract has milestones, and contract.disputed when it does not.

raisedBy is ThirdParty when the dispute is opened through this API. disputeId is sent as a string.

dispute.created does not include status, previousStatus, or amount. When the dispute is on a milestone, it includes milestoneId.

Contract with milestones​

dispute.created

{
"id": "aa3490f8-6862-404d-8841-f391f4484aa7",
"event": "dispute.created",
"createdAt": "2026-10-06T10:47:41.6640885Z",
"data": {
"contractId": "CNT-01M48D4SZYAW",
"milestoneId": "MST-01M48D4SZHR5",
"disputeId": "774",
"raisedBy": "ThirdParty",
"currency": "SAR",
"timestamp": "2026-10-06T10:47:41.6619642Z"
}
}

milestone.disputed

The milestone status stays Escrow. The contract moves to Dispute in contractStatus.

{
"id": "25e9385e-58fd-431f-a77d-b67ecf2d900c",
"event": "milestone.disputed",
"createdAt": "2026-10-06T10:47:41.6573599Z",
"data": {
"contractId": "CNT-01M48D4SZYAW",
"milestoneId": "MST-01M48D4SZHR5",
"disputeId": "774",
"raisedBy": "ThirdParty",
"status": "Escrow",
"previousStatus": "Pending",
"contractStatus": "Dispute",
"contractPreviousStatus": "Approved",
"amount": 1000,
"currency": "SAR",
"timestamp": "2026-10-06T10:47:41.6542281Z"
}
}

Contract without milestones​

dispute.created omits milestoneId.

{
"id": "342399b5-0f59-4aa7-92a8-efb098cfad12",
"event": "dispute.created",
"createdAt": "2026-10-06T11:32:48.230923Z",
"data": {
"contractId": "CNT-01M48FPS2A4R",
"disputeId": "777",
"raisedBy": "ThirdParty",
"currency": "SAR",
"timestamp": "2026-10-06T11:32:48.2285619Z"
}
}

contract.disputed

status is the contract status. It moves from Escrow to Dispute.

{
"id": "d96b3729-5d4b-446e-9521-b32e3d8813be",
"event": "contract.disputed",
"createdAt": "2026-10-06T11:32:48.2263733Z",
"data": {
"contractId": "CNT-01M48FPS2A4R",
"disputeId": "777",
"raisedBy": "ThirdParty",
"status": "Dispute",
"previousStatus": "Escrow",
"amount": 3000.00,
"currency": "SAR",
"timestamp": "2026-10-06T11:32:48.2241167Z"
}
}