From fdd499c0ccbb20bc023bcd00968c0fe4a8d07226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matou=C5=A1=20Dzivjak?= Date: Thu, 21 May 2026 12:40:59 +0200 Subject: [PATCH] feat(sdk): document exceptions Add exceptions to doc strings. Unfortunately, they can't be expressed via the type system so this seems to be the closest option we can use that's commonly used in Python. Related: https://github.com/sumup/sumup-py/issues/299 --- codegen/pkg/builder/doc.go | 43 ++++++++++- codegen/pkg/builder/doc_test.go | 52 ++++++++++++++ codegen/pkg/builder/methods.go | 2 +- sumup/checkouts/resource.py | 106 +++++++++++++++++++++++++++ sumup/customers/resource.py | 84 ++++++++++++++++++++++ sumup/members/resource.py | 70 ++++++++++++++++++ sumup/memberships/resource.py | 14 ++++ sumup/merchants/resource.py | 36 ++++++++++ sumup/payouts/resource.py | 14 ++++ sumup/readers/resource.py | 124 ++++++++++++++++++++++++++++++++ sumup/receipts/resource.py | 16 +++++ sumup/roles/resource.py | 66 +++++++++++++++++ sumup/transactions/resource.py | 42 +++++++++++ 13 files changed, 667 insertions(+), 2 deletions(-) create mode 100644 codegen/pkg/builder/doc_test.go diff --git a/codegen/pkg/builder/doc.go b/codegen/pkg/builder/doc.go index 5ff22ab..edbdd84 100644 --- a/codegen/pkg/builder/doc.go +++ b/codegen/pkg/builder/doc.go @@ -26,7 +26,7 @@ func deprecationNotice(operation *v3.Operation) *string { } // methodDoc creates godoc comment for an operation. -func methodDoc(operation *v3.Operation) string { +func methodDoc(operation *v3.Operation, responses []Response) string { out := new(strings.Builder) if operation.Summary != "" { @@ -44,9 +44,50 @@ func methodDoc(operation *v3.Operation) string { fmt.Fprintf(out, "\n%s: %s\n", extDescription, operation.ExternalDocs.URL) } + if raisesDoc := methodRaisesDoc(responses); raisesDoc != "" { + fmt.Fprintf(out, "\n\n%s", raisesDoc) + } + return formatDoc(out.String()) } +func methodRaisesDoc(responses []Response) string { + errorDescriptions := make([]string, 0, len(responses)) + + for _, response := range responses { + if !response.IsErr { + continue + } + + description := response.ErrDescription + if description == "" { + description = "the API returns an error response" + } + + if response.IsDefault { + errorDescriptions = append(errorDescriptions, description) + continue + } + + errorDescriptions = append(errorDescriptions, fmt.Sprintf("%d: %s", response.Code, description)) + } + + out := new(strings.Builder) + out.WriteString("Raises:\n") + if len(errorDescriptions) == 0 { + out.WriteString(" APIError: Raised when the API returns an unexpected response.") + return out.String() + } + + out.WriteString(" APIError: Raised when the API returns one of the documented error responses:\n") + for _, description := range errorDescriptions { + fmt.Fprintf(out, " %s\n", description) + } + out.WriteString(" Unexpected response statuses also raise this exception.") + + return out.String() +} + // schemaDoc creates godoc for a schema. func schemaDoc(name string, schema *base.Schema) string { out := new(strings.Builder) diff --git a/codegen/pkg/builder/doc_test.go b/codegen/pkg/builder/doc_test.go new file mode 100644 index 0000000..223aba4 --- /dev/null +++ b/codegen/pkg/builder/doc_test.go @@ -0,0 +1,52 @@ +package builder + +import ( + "strings" + "testing" + + v3 "github.com/pb33f/libopenapi/datamodel/high/v3" +) + +func TestMethodDocIncludesRaisesForDocumentedErrors(t *testing.T) { + t.Parallel() + + doc := methodDoc(&v3.Operation{ + Summary: "Create a checkout", + Description: "Creates a new checkout.", + }, []Response{ + {Code: 201}, + {Code: 400, IsErr: true, ErrDescription: "The request body is invalid."}, + {Code: 401, IsErr: true, ErrDescription: "The request is not authorized."}, + }) + + if !strings.Contains(doc, "Raises:\n APIError:") { + t.Fatalf("expected Raises section in docstring, got %q", doc) + } + + if !strings.Contains(doc, "400: The request body is invalid.") { + t.Fatalf("expected 400 response in Raises section, got %q", doc) + } + + if !strings.Contains(doc, "401: The request is not authorized.") { + t.Fatalf("expected 401 response in Raises section, got %q", doc) + } + + if !strings.Contains(doc, "Unexpected response statuses also raise this exception.") { + t.Fatalf("expected unexpected response note in Raises section, got %q", doc) + } +} + +func TestMethodDocIncludesRaisesForUnexpectedResponsesOnly(t *testing.T) { + t.Parallel() + + doc := methodDoc(&v3.Operation{ + Summary: "Ping", + Description: "Checks service health.", + }, []Response{ + {Code: 204}, + }) + + if !strings.Contains(doc, "Raises:\n APIError: Raised when the API returns an unexpected response.") { + t.Fatalf("expected fallback Raises section in docstring, got %q", doc) + } +} diff --git a/codegen/pkg/builder/methods.go b/codegen/pkg/builder/methods.go index e164928..c6f3aae 100644 --- a/codegen/pkg/builder/methods.go +++ b/codegen/pkg/builder/methods.go @@ -241,7 +241,7 @@ func (b *Builder) operationToMethod(method, path string, o *v3.Operation) (*Meth ) return &Method{ - Description: methodDoc(o), + Description: methodDoc(o, responses), DeprecationNotice: deprecationNotice(o), Method: strings.ToLower(method), FunctionName: methodName, diff --git a/sumup/checkouts/resource.py b/sumup/checkouts/resource.py index d49eb96..64899f2 100755 --- a/sumup/checkouts/resource.py +++ b/sumup/checkouts/resource.py @@ -329,6 +329,12 @@ def list_available_payment_methods( Get available payment methods Get payment methods available for the given merchant to use with a checkout. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted query parameters. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(amount, NotGivenType) and amount is not None: @@ -377,6 +383,15 @@ def create( To use the [Hosted Checkout](https://developer.sumup.com/online-payments/checkouts/hosted-checkout/) page, setthe `hosted_checkout.enabled` to `true`. Follow by processing a checkout to charge the provided payment instrument. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request body is invalid. + 401: The request is not authorized. + 403: The request isn't sufficiently authorized to create a checkout. + 409: A checkout already exists for the provided unique parameters. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["checkout_reference"] = checkout_reference @@ -436,6 +451,12 @@ def list( List checkouts Lists created checkout resources according to the applied `checkout_reference`. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(checkout_reference, NotGivenType) and checkout_reference is not None: @@ -460,6 +481,13 @@ def get(self, id: str, headers: typing.Optional[HeaderTypes] = None) -> Checkout Retrieve a checkout Retrieves an identified checkout resource. Use this request after processing a checkout to confirm its status and informthe end user respectively. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/checkouts/{id}", @@ -499,6 +527,15 @@ def process( Processing a checkout will attempt to charge the provided payment instrument for the amount of the specified checkout resourceinitiated in the `Create a checkout` endpoint. Follow this request with `Retrieve a checkout` to confirm its status. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request body is invalid for processing the checkout. + 401: The request is not authorized. + 404: The requested resource does not exist. + 409: The request conflicts with the current state of the resource. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["payment_type"] = payment_type @@ -556,6 +593,14 @@ def deactivate(self, id: str, headers: typing.Optional[HeaderTypes] = None) -> C Deactivate a checkout Deactivates an identified checkout resource. If the checkout has already been processed it can not be deactivated. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 404: The requested resource does not exist. + 409: The request conflicts with the current state of the resource. + Unexpected response statuses also raise this exception. """ resp = self._client.delete( f"/v0.1/checkouts/{id}", @@ -592,6 +637,14 @@ def create_apple_pay_session( `ApplePaySession.completeMerchantValidation(...)` in the browser. SumUp validates the merchant session request and returns the Apple Pay session object that your frontend should pass to Apple's JavaScript API. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Bad Request + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["context"] = context @@ -634,6 +687,12 @@ async def list_available_payment_methods( Get available payment methods Get payment methods available for the given merchant to use with a checkout. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted query parameters. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(amount, NotGivenType) and amount is not None: @@ -682,6 +741,15 @@ async def create( To use the [Hosted Checkout](https://developer.sumup.com/online-payments/checkouts/hosted-checkout/) page, setthe `hosted_checkout.enabled` to `true`. Follow by processing a checkout to charge the provided payment instrument. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request body is invalid. + 401: The request is not authorized. + 403: The request isn't sufficiently authorized to create a checkout. + 409: A checkout already exists for the provided unique parameters. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["checkout_reference"] = checkout_reference @@ -741,6 +809,12 @@ async def list( List checkouts Lists created checkout resources according to the applied `checkout_reference`. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(checkout_reference, NotGivenType) and checkout_reference is not None: @@ -765,6 +839,13 @@ async def get(self, id: str, headers: typing.Optional[HeaderTypes] = None) -> Ch Retrieve a checkout Retrieves an identified checkout resource. Use this request after processing a checkout to confirm its status and informthe end user respectively. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/checkouts/{id}", @@ -804,6 +885,15 @@ async def process( Processing a checkout will attempt to charge the provided payment instrument for the amount of the specified checkout resourceinitiated in the `Create a checkout` endpoint. Follow this request with `Retrieve a checkout` to confirm its status. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request body is invalid for processing the checkout. + 401: The request is not authorized. + 404: The requested resource does not exist. + 409: The request conflicts with the current state of the resource. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["payment_type"] = payment_type @@ -861,6 +951,14 @@ async def deactivate(self, id: str, headers: typing.Optional[HeaderTypes] = None Deactivate a checkout Deactivates an identified checkout resource. If the checkout has already been processed it can not be deactivated. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 404: The requested resource does not exist. + 409: The request conflicts with the current state of the resource. + Unexpected response statuses also raise this exception. """ resp = await self._client.delete( f"/v0.1/checkouts/{id}", @@ -897,6 +995,14 @@ async def create_apple_pay_session( `ApplePaySession.completeMerchantValidation(...)` in the browser. SumUp validates the merchant session request and returns the Apple Pay session object that your frontend should pass to Apple's JavaScript API. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Bad Request + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["context"] = context diff --git a/sumup/customers/resource.py b/sumup/customers/resource.py index c3db255..7c1d634 100755 --- a/sumup/customers/resource.py +++ b/sumup/customers/resource.py @@ -89,6 +89,15 @@ def create( Create a customer Creates a new saved customer resource which you can later manipulate and save payment instruments to. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request body is invalid. + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 409: A customer with the provided identifier already exists. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["customer_id"] = customer_id @@ -128,6 +137,14 @@ def get(self, customer_id: str, headers: typing.Optional[HeaderTypes] = None) -> Retrieve a customer Retrieves an identified saved customer resource through the unique `customer_id` parameter, generated upon customer creation. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/customers/{customer_id}", @@ -165,6 +182,14 @@ def update( Updates an identified saved customer resource's personal details. The request only overwrites the parameters included in the request, all other parameters will remain with theirinitially assigned values. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(personal_details, NotGivenType): @@ -201,6 +226,14 @@ def list_payment_instruments( List payment instruments Lists all payment instrument resources that are saved for an identified customer. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/customers/{customer_id}/payment-instruments", @@ -234,6 +267,15 @@ def deactivate_payment_instrument( Deactivate a payment instrument Deactivates an identified card payment instrument resource for a customer. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid. + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = self._client.delete( f"/v0.1/customers/{customer_id}/payment-instruments/{token}", @@ -278,6 +320,15 @@ async def create( Create a customer Creates a new saved customer resource which you can later manipulate and save payment instruments to. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request body is invalid. + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 409: A customer with the provided identifier already exists. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["customer_id"] = customer_id @@ -317,6 +368,14 @@ async def get(self, customer_id: str, headers: typing.Optional[HeaderTypes] = No Retrieve a customer Retrieves an identified saved customer resource through the unique `customer_id` parameter, generated upon customer creation. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/customers/{customer_id}", @@ -354,6 +413,14 @@ async def update( Updates an identified saved customer resource's personal details. The request only overwrites the parameters included in the request, all other parameters will remain with theirinitially assigned values. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(personal_details, NotGivenType): @@ -390,6 +457,14 @@ async def list_payment_instruments( List payment instruments Lists all payment instrument resources that are saved for an identified customer. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/customers/{customer_id}/payment-instruments", @@ -423,6 +498,15 @@ async def deactivate_payment_instrument( Deactivate a payment instrument Deactivates an identified card payment instrument resource for a customer. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid. + 401: The request is not authorized. + 403: The request is authenticated but not permitted for this operation. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ resp = await self._client.delete( f"/v0.1/customers/{customer_id}/payment-instruments/{token}", diff --git a/sumup/members/resource.py b/sumup/members/resource.py index 97a5fd7..4ab19b6 100755 --- a/sumup/members/resource.py +++ b/sumup/members/resource.py @@ -175,6 +175,12 @@ def list( List members Lists merchant members. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(offset, NotGivenType) and offset is not None: @@ -221,6 +227,14 @@ def create( Create a member Create a merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + 429: Too many invitations were sent to that user and the rate limit was exceeded. The Retry-After headerindicates when the client can retry. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(is_managed_user, NotGivenType): @@ -263,6 +277,12 @@ def get( Retrieve a member Retrieve a merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant or member not found. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/merchants/{merchant_code}/members/{member_id}", @@ -290,6 +310,15 @@ def update( Update a member Update the merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Cannot set password or nickname for an invited user. + 403: Cannot change password for managed user. Password was already used before. + 404: Merchant or member not found. + 409: Cannot update member as some data conflict with existing members. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(roles, NotGivenType): @@ -338,6 +367,12 @@ def delete( Delete a member Deletes a merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant or member not found. + Unexpected response statuses also raise this exception. """ resp = self._client.delete( f"/v0.1/merchants/{merchant_code}/members/{member_id}", @@ -374,6 +409,12 @@ async def list( List members Lists merchant members. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(offset, NotGivenType) and offset is not None: @@ -420,6 +461,14 @@ async def create( Create a member Create a merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + 429: Too many invitations were sent to that user and the rate limit was exceeded. The Retry-After headerindicates when the client can retry. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(is_managed_user, NotGivenType): @@ -462,6 +511,12 @@ async def get( Retrieve a member Retrieve a merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant or member not found. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/merchants/{merchant_code}/members/{member_id}", @@ -489,6 +544,15 @@ async def update( Update a member Update the merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Cannot set password or nickname for an invited user. + 403: Cannot change password for managed user. Password was already used before. + 404: Merchant or member not found. + 409: Cannot update member as some data conflict with existing members. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(roles, NotGivenType): @@ -537,6 +601,12 @@ async def delete( Delete a member Deletes a merchant member. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant or member not found. + Unexpected response statuses also raise this exception. """ resp = await self._client.delete( f"/v0.1/merchants/{merchant_code}/members/{member_id}", diff --git a/sumup/memberships/resource.py b/sumup/memberships/resource.py index c2f40a7..65dd4eb 100755 --- a/sumup/memberships/resource.py +++ b/sumup/memberships/resource.py @@ -78,6 +78,13 @@ def list( List memberships List memberships of the current user. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid query parameter combination. + 401: Authentication failed or missing required scope. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(offset, NotGivenType) and offset is not None: @@ -152,6 +159,13 @@ async def list( List memberships List memberships of the current user. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid query parameter combination. + 401: Authentication failed or missing required scope. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(offset, NotGivenType) and offset is not None: diff --git a/sumup/merchants/resource.py b/sumup/merchants/resource.py index f6da43a..cf5f2eb 100755 --- a/sumup/merchants/resource.py +++ b/sumup/merchants/resource.py @@ -65,6 +65,12 @@ def get( Retrieve a merchant. Merchant documentation: https://developer.sumup.com/tools/models/merchant + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Merchant does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(version, NotGivenType) and version is not None: @@ -97,6 +103,12 @@ def list_persons( Returns a list of persons related to the merchant. Persons documentation: https://developer.sumup.com/tools/models/merchant#persons + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Merchant does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(version, NotGivenType) and version is not None: @@ -130,6 +142,12 @@ def get_person( Returns a single person related to the merchant. Persons documentation: https://developer.sumup.com/tools/models/merchant#persons + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Person does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(version, NotGivenType) and version is not None: @@ -169,6 +187,12 @@ async def get( Retrieve a merchant. Merchant documentation: https://developer.sumup.com/tools/models/merchant + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Merchant does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(version, NotGivenType) and version is not None: @@ -201,6 +225,12 @@ async def list_persons( Returns a list of persons related to the merchant. Persons documentation: https://developer.sumup.com/tools/models/merchant#persons + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Merchant does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(version, NotGivenType) and version is not None: @@ -234,6 +264,12 @@ async def get_person( Returns a single person related to the merchant. Persons documentation: https://developer.sumup.com/tools/models/merchant#persons + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Person does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(version, NotGivenType) and version is not None: diff --git a/sumup/payouts/resource.py b/sumup/payouts/resource.py index 8d18b3b..becf17c 100755 --- a/sumup/payouts/resource.py +++ b/sumup/payouts/resource.py @@ -56,6 +56,13 @@ def list( - deduction records for refunds, chargebacks, direct debit returns, or balance adjustments Results are sorted by payout date in the requested `order`. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted query parameters. + 401: The request is not authorized. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} query_data["start_date"] = start_date @@ -115,6 +122,13 @@ async def list( - deduction records for refunds, chargebacks, direct debit returns, or balance adjustments Results are sorted by payout date in the requested `order`. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted query parameters. + 401: The request is not authorized. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} query_data["start_date"] = start_date diff --git a/sumup/readers/resource.py b/sumup/readers/resource.py index caec017..95e5e24 100755 --- a/sumup/readers/resource.py +++ b/sumup/readers/resource.py @@ -301,6 +301,12 @@ def list( List Readers List all readers of the merchant. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: Authentication failed or missing required scope. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/merchants/{merchant_code}/readers", @@ -330,6 +336,14 @@ def create( Create a Reader Create a new Reader for the merchant account. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid. + 404: There's no pending reader for the submitted pairing code. + 409: The Reader is not in a pending state. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["pairing_code"] = pairing_code @@ -366,6 +380,12 @@ def get( Retrieve a Reader Retrieve a Reader. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Reader resource does not exist. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/merchants/{merchant_code}/readers/{id}", @@ -389,6 +409,12 @@ def delete( Delete a reader Delete a reader. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Reader resource does not exist. + Unexpected response statuses also raise this exception. """ resp = self._client.delete( f"/v0.1/merchants/{merchant_code}/readers/{id}", @@ -418,6 +444,13 @@ def update( Update a Reader Update a Reader. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 403: The request isn't sufficiently authorized to modify the reader. + 404: The requested Reader resource does not exist. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(name, NotGivenType): @@ -481,6 +514,16 @@ def create_checkout( **Note**: If the target device is a Solo, it must be in version 3.3.24.3 or higher. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Response when given params (or one of them) are invalid + 401: Unauthorized + 404: Response when given reader is not found + 422: Response when given params (or one of them) are invalid + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(aade, NotGivenType): @@ -554,6 +597,15 @@ def get_status( * `OFFLINE` – Device disconnected (last state persisted) **Note**: If the target device is a Solo, it must be in version 3.3.39.0 or higher. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Response when given params (or one of them) are invalid + 401: Response when given merchant's token is invalid + 404: Response when given reader is not found + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/merchants/{merchant_code}/readers/{reader_id}/status", @@ -600,6 +652,16 @@ def terminate_checkout( **Note**: If the target device is a Solo, it must be in version 3.3.28.0 or higher. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Response when given params (or one of them) are invalid + 401: Unauthorized + 404: Response when given reader is not found + 422: Response when given params (or one of them) are invalid + Unexpected response statuses also raise this exception. """ resp = self._client.post( f"/v0.1/merchants/{merchant_code}/readers/{reader_id}/terminate", @@ -642,6 +704,12 @@ async def list( List Readers List all readers of the merchant. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: Authentication failed or missing required scope. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/merchants/{merchant_code}/readers", @@ -671,6 +739,14 @@ async def create( Create a Reader Create a new Reader for the merchant account. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid. + 404: There's no pending reader for the submitted pairing code. + 409: The Reader is not in a pending state. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["pairing_code"] = pairing_code @@ -707,6 +783,12 @@ async def get( Retrieve a Reader Retrieve a Reader. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Reader resource does not exist. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/merchants/{merchant_code}/readers/{id}", @@ -730,6 +812,12 @@ async def delete( Delete a reader Delete a reader. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested Reader resource does not exist. + Unexpected response statuses also raise this exception. """ resp = await self._client.delete( f"/v0.1/merchants/{merchant_code}/readers/{id}", @@ -759,6 +847,13 @@ async def update( Update a Reader Update a Reader. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 403: The request isn't sufficiently authorized to modify the reader. + 404: The requested Reader resource does not exist. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(name, NotGivenType): @@ -822,6 +917,16 @@ async def create_checkout( **Note**: If the target device is a Solo, it must be in version 3.3.24.3 or higher. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Response when given params (or one of them) are invalid + 401: Unauthorized + 404: Response when given reader is not found + 422: Response when given params (or one of them) are invalid + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(aade, NotGivenType): @@ -895,6 +1000,15 @@ async def get_status( * `OFFLINE` – Device disconnected (last state persisted) **Note**: If the target device is a Solo, it must be in version 3.3.39.0 or higher. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Response when given params (or one of them) are invalid + 401: Response when given merchant's token is invalid + 404: Response when given reader is not found + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/merchants/{merchant_code}/readers/{reader_id}/status", @@ -941,6 +1055,16 @@ async def terminate_checkout( **Note**: If the target device is a Solo, it must be in version 3.3.28.0 or higher. + + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Response when given params (or one of them) are invalid + 401: Unauthorized + 404: Response when given reader is not found + 422: Response when given params (or one of them) are invalid + Unexpected response statuses also raise this exception. """ resp = await self._client.post( f"/v0.1/merchants/{merchant_code}/readers/{reader_id}/terminate", diff --git a/sumup/receipts/resource.py b/sumup/receipts/resource.py index ada863d..3c4674b 100755 --- a/sumup/receipts/resource.py +++ b/sumup/receipts/resource.py @@ -54,6 +54,14 @@ def get( Retrieve receipt details Retrieves receipt specific data for a transaction. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted parameters. + 401: The request is not authorized. + 404: The requested transaction event does not exist for the provided transaction. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} query_data["mid"] = mid @@ -105,6 +113,14 @@ async def get( Retrieve receipt details Retrieves receipt specific data for a transaction. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted parameters. + 401: The request is not authorized. + 404: The requested transaction event does not exist for the provided transaction. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} query_data["mid"] = mid diff --git a/sumup/roles/resource.py b/sumup/roles/resource.py index 82a973c..1dc2873 100755 --- a/sumup/roles/resource.py +++ b/sumup/roles/resource.py @@ -93,6 +93,12 @@ def list( List roles List merchant's custom roles. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/merchants/{merchant_code}/roles", @@ -119,6 +125,13 @@ def create( Create a role Create a custom role for the merchant. Roles are defined by the set of permissions that they grant to the members thatthey are assigned to. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["name"] = name @@ -149,6 +162,12 @@ def get( Retrieve a role Retrieve a custom role by ID. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant or role not found. + Unexpected response statuses also raise this exception. """ resp = self._client.get( f"/v0.1/merchants/{merchant_code}/roles/{role_id}", @@ -168,6 +187,13 @@ def delete( Delete a role Delete a custom role. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ resp = self._client.delete( f"/v0.1/merchants/{merchant_code}/roles/{role_id}", @@ -196,6 +222,13 @@ def update( Update a role Update a custom role. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(name, NotGivenType): @@ -233,6 +266,12 @@ async def list( List roles List merchant's custom roles. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/merchants/{merchant_code}/roles", @@ -259,6 +298,13 @@ async def create( Create a role Create a custom role for the merchant. Roles are defined by the set of permissions that they grant to the members thatthey are assigned to. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} body_data["name"] = name @@ -289,6 +335,12 @@ async def get( Retrieve a role Retrieve a custom role by ID. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: Merchant or role not found. + Unexpected response statuses also raise this exception. """ resp = await self._client.get( f"/v0.1/merchants/{merchant_code}/roles/{role_id}", @@ -308,6 +360,13 @@ async def delete( Delete a role Delete a custom role. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ resp = await self._client.delete( f"/v0.1/merchants/{merchant_code}/roles/{role_id}", @@ -336,6 +395,13 @@ async def update( Update a role Update a custom role. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: Invalid request. + 404: Merchant not found. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(name, NotGivenType): diff --git a/sumup/transactions/resource.py b/sumup/transactions/resource.py index aac1485..1c4e98b 100755 --- a/sumup/transactions/resource.py +++ b/sumup/transactions/resource.py @@ -123,6 +123,13 @@ def refund( Refund a transaction Refunds an identified transaction either in full or partially. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested resource does not exist. + 409: The transaction cannot be refunded due to business constraints. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(amount, NotGivenType): @@ -166,6 +173,13 @@ def get( - `transaction_code` - `foreign_transaction_id` - `client_transaction_id` + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(id, NotGivenType) and id is not None: @@ -228,6 +242,13 @@ def list( List transactions Lists detailed history of all transactions associated with the merchant profile. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted query parameters. + 401: The request is not authorized. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(transaction_code, NotGivenType) and transaction_code is not None: @@ -296,6 +317,13 @@ async def refund( Refund a transaction Refunds an identified transaction either in full or partially. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 404: The requested resource does not exist. + 409: The transaction cannot be refunded due to business constraints. + Unexpected response statuses also raise this exception. """ body_data: dict[str, typing.Any] = {} if not isinstance(amount, NotGivenType): @@ -339,6 +367,13 @@ async def get( - `transaction_code` - `foreign_transaction_id` - `client_transaction_id` + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 401: The request is not authorized. + 404: The requested resource does not exist. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(id, NotGivenType) and id is not None: @@ -401,6 +436,13 @@ async def list( List transactions Lists detailed history of all transactions associated with the merchant profile. + + + Raises: + APIError: Raised when the API returns one of the documented error responses: + 400: The request is invalid for the submitted query parameters. + 401: The request is not authorized. + Unexpected response statuses also raise this exception. """ query_data: dict[str, typing.Any] = {} if not isinstance(transaction_code, NotGivenType) and transaction_code is not None: