Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d5bbdd1
Changes generated by c156f883b70ffbc2900a2404470770ba1b0295ca
gocardless-robot Dec 4, 2024
3c8bf9a
Changes generated by 9cfa952f153d9ec4557be3927649e25fefecfce3
gocardless-robot Dec 17, 2024
67cadef
Changes generated by cd79117a692509f51a5011dde41402e3c66ee967
gocardless-robot Dec 20, 2024
0e4110e
Changes generated by fab9c63bba795ac1e5f185105ade5275108cfb93
gocardless-robot Jan 10, 2025
bf9e1d2
Changes generated by b7863e576b3169134217df0719e7fca70880d2cd
gocardless-robot Jan 16, 2025
b0a356d
Changes generated by bda373bfb611b0dec014c3e3e74d4a85757c9db2
gocardless-robot Jan 27, 2025
92a7e70
Changes generated by 24621b99f2324b2cb8f106cd9a3fdea396d6d846
gocardless-robot Jan 27, 2025
b87bfce
Changes generated by f584bd724be97d0ef9e8d34d3447988ec13df49a
gocardless-robot Feb 5, 2025
c207832
Changes generated by 7e760f9765f8b56c1a431e752c4ba4e734a29107
gocardless-robot Feb 13, 2025
b2fc736
Changes generated by 65c65b9a7746c36d40a9f75550a40cd2331697ff
gocardless-robot Feb 17, 2025
cafe957
Changes generated by d283945b8bb006c538932c0b9f48aa66eb60d402
gocardless-robot Feb 24, 2025
dcb30e9
Changes generated by 6d3479328b4f86ef432c68a01174c13b83c28628
gocardless-robot Feb 25, 2025
9a4eb60
Changes generated by 7c5d6835102f78ffe936055ea7b2a95b51192e64
gocardless-robot Feb 25, 2025
62ca7a7
Changes generated by df6da744f04dfe227fd8611e5579a61d10bc661f
gocardless-robot Feb 27, 2025
102f66b
Changes generated by 17716b63ee8ca2e5af9bca8294040d8d1a83d0e7
gocardless-robot Mar 17, 2025
83964f9
Changes generated by f49b185fd6e854050af8d3821754e6a3a9d0914b
gocardless-robot Mar 25, 2025
a0f8035
Changes generated by 82ebf3c7aa795eccb3ee29d200b7ae5fee45f0df
gocardless-robot Mar 25, 2025
f46fd3c
Changes generated by f2876ec8ec4bc6f0d839e1177ff427c882045baf
gocardless-ci-robot[bot] Mar 26, 2025
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
<!-- @format -->
# 2.3.0

- Added new endpoint `/balance` that the balances for a creditor

# 2.2.0

- Added `status` filter parameter to Mandate Import Entries.
- Added `processing_errors` response field to Mandate Import Entry.

# 2.1.0

- Added `mandate_request[consent_type]` parameter to Billing Request creation.
Expand Down
17 changes: 17 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ For full documentation, see our `API reference`_.
Available resources
```````````````````

Balances
''''''''''''''''''''''''''''''''''''''''''

.. code:: python

# List balances
client.balances.list(params={...})

# Iterate through all balances
client.balances.all(params={...})

Bank authorisations
''''''''''''''''''''''''''''''''''''''''''

Expand Down Expand Up @@ -103,6 +114,12 @@ Billing requests
# Create a Billing Request
client.billing_requests.create(params={...})

# [ACH/PAD only] Create a Billing Request with instalments (with dates)
client.billing_requests.create_with_instalments_with_dates(params={...})

# [ACH/PAD only] Create a Billing Request with instalments (with schedule)
client.billing_requests.create_with_instalments_with_schedule(params={...})

# Collect customer details
client.billing_requests.collect_customer_details('BRQ123', params={...})

Expand Down
2 changes: 1 addition & 1 deletion gocardless_pro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

from .client import Client

__version__ = '2.1.0'
__version__ = '2.3.0'

4 changes: 2 additions & 2 deletions gocardless_pro/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def _default_headers(self):
'Authorization': 'Bearer {0}'.format(self.access_token),
'Content-Type': 'application/json',
'GoCardless-Client-Library': 'gocardless-pro-python',
'GoCardless-Client-Version': '2.1.0',
'GoCardless-Client-Version': '2.3.0',
'User-Agent': self._user_agent(),
'GoCardless-Version': '2015-07-06',
}
Expand All @@ -159,7 +159,7 @@ def _user_agent(self):
python_version = '.'.join(platform.python_version_tuple()[0:2])
vm_version = '{}.{}.{}-{}{}'.format(*sys.version_info)
return ' '.join([
'gocardless-pro-python/2.1.0',
'gocardless-pro-python/2.3.0',
'python/{0}'.format(python_version),
'{0}/{1}'.format(platform.python_implementation(), vm_version),
'{0}/{1}'.format(platform.system(), platform.release()),
Expand Down
4 changes: 4 additions & 0 deletions gocardless_pro/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def __init__(self, access_token=None, environment=None, base_url=None, raise_on_
self._api_client = ApiClient(base_url, access_token)
self._raise_on_idempotency_conflict = raise_on_idempotency_conflict

@property
def balances(self):
return services.BalancesService(self._api_client, 3, 0.5, self._raise_on_idempotency_conflict)

@property
def bank_authorisations(self):
return services.BankAuthorisationsService(self._api_client, 3, 0.5, self._raise_on_idempotency_conflict)
Expand Down
2 changes: 2 additions & 0 deletions gocardless_pro/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# https://github.com/gocardless/crank
#

from .balance import Balance

from .bank_authorisation import BankAuthorisation

from .bank_details_lookup import BankDetailsLookup
Expand Down
65 changes: 65 additions & 0 deletions gocardless_pro/resources/balance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# WARNING: Do not edit by hand, this file was generated by Crank:
#
# https://github.com/gocardless/crank
#

class Balance(object):
"""A thin wrapper around a balance, providing easy access to its
attributes.

Example:
balance = client.balances.get()
balance.id
"""

def __init__(self, attributes, api_response):
self.attributes = attributes
self.api_response = api_response

@property
def amount(self):
return self.attributes.get('amount')


@property
def balance_type(self):
return self.attributes.get('balance_type')


@property
def currency(self):
return self.attributes.get('currency')


@property
def last_updated_at(self):
return self.attributes.get('last_updated_at')


@property
def links(self):
return self.Links(self.attributes.get('links'))












class Links(object):
"""Wrapper for the response's 'links' attribute."""

def __init__(self, attributes):
self.attributes = attributes

@property
def creditor(self):
return self.attributes.get('creditor')



12 changes: 12 additions & 0 deletions gocardless_pro/resources/billing_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ def currency(self):
def instalments(self):
return self.attributes.get('instalments')

@property
def instalments_with_dates(self):
return self.attributes.get('instalments_with_dates')

@property
def instalments_with_schedule(self):
return self.attributes.get('instalments_with_schedule')

@property
def links(self):
return self.attributes.get('links')
Expand Down Expand Up @@ -254,6 +262,10 @@ def payer_requested_dual_signature(self):
def scheme(self):
return self.attributes.get('scheme')

@property
def sweeping(self):
return self.attributes.get('sweeping')

@property
def verify(self):
return self.attributes.get('verify')
Expand Down
7 changes: 7 additions & 0 deletions gocardless_pro/resources/mandate_import_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ def links(self):
return self.Links(self.attributes.get('links'))


@property
def processing_errors(self):
return self.attributes.get('processing_errors')


@property
def record_identifier(self):
return self.attributes.get('record_identifier')
Expand Down Expand Up @@ -61,3 +66,5 @@ def mandate_import(self):





1 change: 1 addition & 0 deletions gocardless_pro/services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# https://github.com/gocardless/crank
#

from .balances_service import BalancesService
from .bank_authorisations_service import BankAuthorisationsService
from .bank_details_lookups_service import BankDetailsLookupsService
from .billing_requests_service import BillingRequestsService
Expand Down
45 changes: 45 additions & 0 deletions gocardless_pro/services/balances_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# WARNING: Do not edit by hand, this file was generated by Crank:
#
# https://github.com/gocardless/crank
#

from . import base_service
from .. import resources
from ..paginator import Paginator
from .. import errors

class BalancesService(base_service.BaseService):
"""Service class that provides access to the balances
endpoints of the GoCardless Pro API.
"""

RESOURCE_CLASS = resources.Balance
RESOURCE_NAME = 'balances'


def list(self,params=None, headers=None):
"""List balances.

Returns a [cursor-paginated](#api-usage-cursor-pagination) list of
balances for a given creditor. This endpoint is rate limited to 60
requests per minute.

Args:
params (dict, optional): Query string parameters.

Returns:
ListResponse of Balance instances
"""
path = '/balances'


response = self._perform_request('GET', path, params, headers,
retry_failures=True)
return self._resource_for(response)

def all(self, params=None):
if params is None:
params = {}
return Paginator(self, params)


64 changes: 62 additions & 2 deletions gocardless_pro/services/billing_requests_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,68 @@ def create(self,params=None, headers=None):
"""Create a Billing Request.

<p class="notice"><strong>Important</strong>: All properties associated
with `subscription_request` and `instalment_schedule_request` are only
supported for ACH and PAD schemes.</p>
with `subscription_request` are only supported for ACH and PAD
schemes.</p>

Args:
params (dict, optional): Request body.

Returns:
BillingRequest
"""
path = '/billing_requests'

if params is not None:
params = {self._envelope_key(): params}

try:
response = self._perform_request('POST', path, params, headers,
retry_failures=True)
except errors.IdempotentCreationConflictError as err:
if self.raise_on_idempotency_conflict:
raise err
return self.get(identity=err.conflicting_resource_id,
params=params,
headers=headers)
return self._resource_for(response)


def create_with_instalments_with_dates(self,params=None, headers=None):
"""[ACH/PAD only] Create a Billing Request with instalments (with dates).

<p class="notice"><strong>Important</strong>: All properties associated
with `instalment_schedule_request` are only supported for ACH and PAD
schemes.</p>

Args:
params (dict, optional): Request body.

Returns:
BillingRequest
"""
path = '/billing_requests'

if params is not None:
params = {self._envelope_key(): params}

try:
response = self._perform_request('POST', path, params, headers,
retry_failures=True)
except errors.IdempotentCreationConflictError as err:
if self.raise_on_idempotency_conflict:
raise err
return self.get(identity=err.conflicting_resource_id,
params=params,
headers=headers)
return self._resource_for(response)


def create_with_instalments_with_schedule(self,params=None, headers=None):
"""[ACH/PAD only] Create a Billing Request with instalments (with schedule).

<p class="notice"><strong>Important</strong>: All properties associated
with `instalment_schedule_request` are only supported for ACH and PAD
schemes.</p>

Args:
params (dict, optional): Request body.
Expand Down
4 changes: 2 additions & 2 deletions gocardless_pro/services/refunds_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def create(self,params=None, headers=None):
is there to prevent two processes from creating refunds without
awareness of each other.

- `number_of_refunds_exceeded` if five or more refunds have already
been created against the payment.
- `number_of_refunds_exceeded` if twenty five or more refunds have
already been created against the payment.

- `available_refund_amount_insufficient` if the creditor does not have
sufficient balance for refunds available to cover the cost of the
Expand Down
2 changes: 1 addition & 1 deletion gocardless_pro/services/scenario_simulators_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def run(self,identity,params=None, headers=None):
<li>`payment_failed`: Transitions a payment through to `failed`. It must start in the `pending_submission` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment).</li>
<li>`payment_charged_back`: Behaves the same as the `payout_paid_out` simulator, except that the payment is transitioned to `charged_back` after it is paid out, having been charged back by the customer.</li>
<li>`payment_chargeback_settled`: Behaves the same as the `payment_charged_back` simulator, except that the charged back payment is additionally included as a debit item in a payout, thereby settling the charged back payment.</li>
<li>`payment_late_failure`: Transitions a payment through to `late_failure`, having been apparently collected successfully beforehand. It must start in the `pending_submission` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment). Not compatible with Autogiro mandates.</li>
<li>`payment_late_failure`: Transitions a payment through to `late_failure`, having been apparently collected successfully beforehand. It must start in either the `pending_submission` or `paid_out` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment). Not compatible with Autogiro mandates.</li>
<li>`payment_late_failure_settled`: Behaves the same as the `payment_late_failure` simulator, except that the late failure is additionally included as a debit item in a payout, thereby settling the late failure.</li>
<li>`payment_submitted`: Transitions a payment to `submitted`, without proceeding any further. It must start in the `pending_submission` state.</li>
<li>`mandate_activated`: Transitions a mandate through to `activated`, having been submitted to the banks and set up successfully. It must start in the `pending_submission` state. Not compatible with ACH, BECS, BECS_NZ and SEPA mandates, which are submitted and activated with their first payment.</li>
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

setup(
name = 'gocardless_pro',
version = '2.1.0',
version = '2.3.0',
packages = find_packages(exclude=['tests']),
install_requires = ['requests>=2.6', 'six'],
author = 'GoCardless',
Expand Down
3 changes: 3 additions & 0 deletions tests/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ def test_requires_valid_environment():
Client(access_token=access_token, environment='invalid')


def test_balances_returns_service():
assert isinstance(client.balances, services.BalancesService)

def test_bank_authorisations_returns_service():
assert isinstance(client.bank_authorisations, services.BankAuthorisationsService)

Expand Down
8 changes: 8 additions & 0 deletions tests/fixtures/balances.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"list": {
"method": "GET",
"path_template": "/balances",
"url_params": [],
"body": {"balances":[{"amount":8081,"balance_type":"confirmed_funds","currency":"EUR","last_updated_at":"2014-01-01T12:00:00.000Z","links":{"creditor":"CR123"}},{"amount":7887,"balance_type":"confirmed_funds","currency":"EUR","last_updated_at":"2014-01-01T12:00:00.000Z","links":{"creditor":"CR123"}}],"meta":{"cursors":{"after":"example after 1847","before":"example before 4059"},"limit":50}}
}
}
4 changes: 2 additions & 2 deletions tests/fixtures/bank_authorisations.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"method": "POST",
"path_template": "/bank_authorisations",
"url_params": [],
"body": {"bank_authorisations":{"authorisation_type":"example authorisation_type 8081","authorised_at":"2020-01-01T12:00:00.000Z","created_at":"2024-12-03T12:55:13.866Z","expires_at":"2024-12-03T12:55:13.866Z","id":"BAU123","last_visited_at":"2020-01-01T12:00:00.000Z","links":{"billing_request":"BRQ123","institution":"monzo"},"qr_code_url":"https://pay.gocardless.com/obauth/BAU123/qr_code","redirect_uri":"https://my-website.com/abc/callback","url":"https://pay.gocardless.com/obauth/BAU123"}}
"body": {"bank_authorisations":{"authorisation_type":"example authorisation_type 2081","authorised_at":"2020-01-01T12:00:00.000Z","created_at":"2025-03-26T11:54:35.418Z","expires_at":"2025-03-26T11:54:35.418Z","id":"BAU123","last_visited_at":"2020-01-01T12:00:00.000Z","links":{"billing_request":"BRQ123","institution":"monzo"},"qr_code_url":"https://pay.gocardless.com/obauth/BAU123/qr_code","redirect_uri":"https://my-website.com/abc/callback","url":"https://pay.gocardless.com/obauth/BAU123"}}
},
"get": {
"method": "GET",
"path_template": "/bank_authorisations/:identity",
"url_params": ["BAU123"],
"body": {"bank_authorisations":{"authorisation_type":"example authorisation_type 7887","authorised_at":"2020-01-01T12:00:00.000Z","created_at":"2024-12-03T12:55:13.866Z","expires_at":"2024-12-03T12:55:13.866Z","id":"BAU123","last_visited_at":"2020-01-01T12:00:00.000Z","links":{"billing_request":"BRQ123","institution":"monzo"},"qr_code_url":"https://pay.gocardless.com/obauth/BAU123/qr_code","redirect_uri":"https://my-website.com/abc/callback","url":"https://pay.gocardless.com/obauth/BAU123"}}
"body": {"bank_authorisations":{"authorisation_type":"example authorisation_type 1318","authorised_at":"2020-01-01T12:00:00.000Z","created_at":"2025-03-26T11:54:35.418Z","expires_at":"2025-03-26T11:54:35.418Z","id":"BAU123","last_visited_at":"2020-01-01T12:00:00.000Z","links":{"billing_request":"BRQ123","institution":"monzo"},"qr_code_url":"https://pay.gocardless.com/obauth/BAU123/qr_code","redirect_uri":"https://my-website.com/abc/callback","url":"https://pay.gocardless.com/obauth/BAU123"}}
}
}
Loading