Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -14285,6 +14285,94 @@
}
},
"webhooks": {
"sales.completed": {
"post": {
"operationId": "SaleCompletedWebhook",
"tags": [
"Sales"
],
"summary": "Sale completed",
"description": "Sent once per sale when its completion is observed: the sale is closed and has been fully paid. The event created_at is the sale's recorded completion time, rather than the time the notification is delivered. A delayed notification may arrive after subsequent updates, refunds, or chargebacks. Fetch the current sale using object.url with an access token that has the sales.read scope. The sale may briefly be unavailable while the Sales API catches up; retry fetching it after a 404 response. Automatic retries and manual redelivery may deliver the same event more than once; deduplicate by event id.",
"x-object-type": "sale",
"x-object": {
"$ref": "#/components/schemas/Sale"
},
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Event"
},
"examples": {
"completed": {
"summary": "A sale completed webhook event.",
"value": {
"id": "event_01JQCG7EF8F2DA02V31HSEXXCM",
"type": "sales.completed",
"created_at": "2026-10-14T12:00:00Z",
"object": {
"id": "847ed267-c617-4d38-9e5a-4ef728daa5c3",
"type": "sale",
"url": "https://api.sumup.com/v1.0/merchants/MC0DE/sales/847ed267-c617-4d38-9e5a-4ef728daa5c3"
}
}
}
}
}
}
},
"responses": {
"2XX": {
"description": "Return any 2xx response to acknowledge successful delivery."
}
}
}
},
"sales.updated": {
"post": {
"operationId": "SaleUpdatedWebhook",
"tags": [
"Sales"
],
"summary": "Sale updated",
"description": "Sent when a closed, fully paid sale is published or updated, including subsequent refunds and chargebacks. The first notification can occur when the sale becomes fully paid and closed. Fetch the current sale using object.url with an access token that has the sales.read scope. The sale may briefly be unavailable while the Sales API catches up; retry fetching it after a 404 response. Notifications contain the sale identity rather than a snapshot, and delivery order is not guaranteed.",
"x-object-type": "sale",
"x-object": {
"$ref": "#/components/schemas/Sale"
},
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Event"
},
"examples": {
"updated": {
"summary": "A sale updated webhook event.",
"value": {
"id": "event_01JQCG7EF8F2DA02V31HSEXXCM",
"type": "sales.updated",
"created_at": "2026-10-14T12:00:00Z",
"object": {
"id": "847ed267-c617-4d38-9e5a-4ef728daa5c3",
"type": "sale",
"url": "https://api.sumup.com/v1.0/merchants/MC0DE/sales/847ed267-c617-4d38-9e5a-4ef728daa5c3"
}
}
}
}
}
}
},
"responses": {
"2XX": {
"description": "Return any 2xx response to acknowledge successful delivery."
}
}
}
},
"checkouts.created": {
"post": {
"operationId": "CheckoutCreatedWebhook",
Expand Down
20 changes: 20 additions & 0 deletions src/SumUp/Events.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public sealed class RoleDeletedEvent : EventNotification<Role>;
/// <summary>Sent when a role is updated for a merchant account.</summary>
public sealed class RoleUpdatedEvent : EventNotification<Role>;

/// <summary>Sent once per sale when its completion is observed: the sale is closed and has been fully paid. The event created_at is the sale's recorded completion time, rather than the time the notification is delivered. A delayed notification may arrive after subsequent updates, refunds, or chargebacks. Fetch the current sale using object.url with an access token that has the sales.read scope. The sale may briefly be unavailable while the Sales API catches up; retry fetching it after a 404 response. Automatic retries and manual redelivery may deliver the same event more than once; deduplicate by event id.</summary>
public sealed class SaleCompletedEvent : EventNotification<Sale>;

/// <summary>Sent when a closed, fully paid sale is published or updated, including subsequent refunds and chargebacks. The first notification can occur when the sale becomes fully paid and closed. Fetch the current sale using object.url with an access token that has the sales.read scope. The sale may briefly be unavailable while the Sales API catches up; retry fetching it after a 404 response. Notifications contain the sale identity rather than a snapshot, and delivery order is not guaranteed.</summary>
public sealed class SaleUpdatedEvent : EventNotification<Sale>;

public sealed partial class EventsHandler
{
/// <summary>Registers a callback for <c>"checkouts.created"</c>, replacing any previous callback for this type.</summary>
Expand Down Expand Up @@ -123,6 +129,18 @@ public EventsHandler OnRoleDeleted(Func<RoleDeletedEvent, CancellationToken, Tas
public EventsHandler OnRoleUpdated(Func<RoleUpdatedEvent, CancellationToken, Task> callback) =>
Register("roles.updated", callback);

/// <summary>Registers a callback for <c>"sales.completed"</c>, replacing any previous callback for this type.</summary>
/// <param name="callback">The callback to await, with the request cancellation token.</param>
/// <returns>This handler, for chaining registrations.</returns>
public EventsHandler OnSaleCompleted(Func<SaleCompletedEvent, CancellationToken, Task> callback) =>
Register("sales.completed", callback);

/// <summary>Registers a callback for <c>"sales.updated"</c>, replacing any previous callback for this type.</summary>
/// <param name="callback">The callback to await, with the request cancellation token.</param>
/// <returns>This handler, for chaining registrations.</returns>
public EventsHandler OnSaleUpdated(Func<SaleUpdatedEvent, CancellationToken, Task> callback) =>
Register("sales.updated", callback);

}

public partial class SumUpClient
Expand All @@ -142,6 +160,8 @@ public partial class SumUpClient
"roles.created" => root.Deserialize<RoleCreatedEvent>()!,
"roles.deleted" => root.Deserialize<RoleDeletedEvent>()!,
"roles.updated" => root.Deserialize<RoleUpdatedEvent>()!,
"sales.completed" => root.Deserialize<SaleCompletedEvent>()!,
"sales.updated" => root.Deserialize<SaleUpdatedEvent>()!,
_ => root.Deserialize<EventNotification>()!,
};
}
Loading