From 522d407789dc8f96523e3e85c0bf8cd447f0d027 Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 15 May 2026 16:02:57 +0200 Subject: [PATCH 1/2] feat(payments): add payouts endpoint --- CHANGELOG.md | 8 +- chift/models/consumers/banking/__init__.py | 16 +- chift/models/consumers/payment/__init__.py | 8 + chift/openapi/models.py | 5 + chift/openapi/openapi.json | 271 +++++++++++++++++++++ chift/openapi/openapi.py | 49 +++- pyproject.toml | 2 +- 7 files changed, 354 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 863917f..fceb56b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.6.1 - 2026-05-15 +- payments: add payout endpoint +- banking: add custom endpoint + ## 0.6.0 - 2026-05-08 - models: allow extra fields @@ -25,10 +29,10 @@ ## 0.5.13 - 2026-03-13 - pms: add transactions model -# 0.5.12 - 2026-03-13 +## 0.5.12 - 2026-03-13 - Fix exception raising when response status is 401 -# 0.5.11 - 2026-03-13 +## 0.5.11 - 2026-03-13 - add create/update/delete endpoints in the Invoicing API ## 0.5.10 - 2026-03-09 diff --git a/chift/models/consumers/banking/__init__.py b/chift/models/consumers/banking/__init__.py index 800dcc0..5aabd09 100644 --- a/chift/models/consumers/banking/__init__.py +++ b/chift/models/consumers/banking/__init__.py @@ -1,6 +1,6 @@ from typing import ClassVar -from chift.api.mixins import ListMixin, PaginationMixin +from chift.api.mixins import CreateMixin, ListMixin, PaginationMixin from chift.openapi.models import BankingAccount as BankingAccountModel from chift.openapi.models import BankingAttachment as BankingAttachmentModel from chift.openapi.models import BankingCounterpart as BankingCounterpartModel @@ -17,6 +17,7 @@ def __init__(self, consumer_id, connection_id): self.Transaction = Transaction(consumer_id, connection_id) self.Counterpart = Counterpart(consumer_id, connection_id) self.Attachment = Attachment(consumer_id, connection_id) + self.Custom = Custom(consumer_id, connection_id) class FinancialInstitution(PaginationMixin[FinancialInstitutionModel]): @@ -47,3 +48,16 @@ class Attachment(ListMixin[BankingAttachmentModel]): chift_vertical: ClassVar = "banking" chift_model: ClassVar = "attachments" model = BankingAttachmentModel + + +class Custom(CreateMixin): + chift_vertical: ClassVar = "banking" + + def __init__(self, consumer_id, connection_id, model="custom"): + super().__init__(consumer_id, connection_id) + self.chift_model = model + + def create(self, custom_path, data, client=None, params=None): + self.chift_model = custom_path + self.chift_model_create = custom_path + return super().create(data, map_model=False, client=client, params=params) diff --git a/chift/models/consumers/payment/__init__.py b/chift/models/consumers/payment/__init__.py index b4666cd..aef1ef8 100644 --- a/chift/models/consumers/payment/__init__.py +++ b/chift/models/consumers/payment/__init__.py @@ -9,6 +9,7 @@ ) from chift.openapi.models import PaymentBalance as PaymentBalanceModel from chift.openapi.models import PaymentPayment as PaymentItemModel +from chift.openapi.models import PaymentPayout as PayoutItemModel from chift.openapi.models import PaymentRefund as RefundItemModel from chift.openapi.models import PaymentTransaction as TransactionModel @@ -19,6 +20,7 @@ def __init__(self, consumer_id, connection_id): self.Balance = Balance(consumer_id, connection_id) self.Payment = Payment(consumer_id, connection_id) self.Refund = Refund(consumer_id, connection_id) + self.Payout = Payout(consumer_id, connection_id) class Transaction(PaginationMixin[TransactionModel]): @@ -43,3 +45,9 @@ class Refund(PaginationMixin[RefundItemModel]): chift_vertical: ClassVar = "payment" chift_model: ClassVar = "refunds" model = RefundItemModel + + +class Payout(PaginationMixin[PayoutItemModel]): + chift_vertical: ClassVar = "payment" + chift_model: ClassVar = "payouts" + model = PayoutItemModel diff --git a/chift/openapi/models.py b/chift/openapi/models.py index 5f8f88f..db251a5 100644 --- a/chift/openapi/models.py +++ b/chift/openapi/models.py @@ -64,6 +64,7 @@ from .openapi import PaymentItemOut, PaymentMethodItem from .openapi import PaymentMethods as PaymentMethodsModel from .openapi import ( + PayoutItemOut, PMSAccountingCategoryItem, PMSAccountingTransactionItem, PMSClosureItem, @@ -603,6 +604,10 @@ class PaymentRefund(RefundItemOut): pass +class PaymentPayout(PayoutItemOut): + pass + + # Banking diff --git a/chift/openapi/openapi.json b/chift/openapi/openapi.json index fb407f9..820ab78 100644 --- a/chift/openapi/openapi.json +++ b/chift/openapi/openapi.json @@ -17625,6 +17625,23 @@ }, "description": "Get all transactions for a specific balance" }, + { + "name": "payout_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Payout Id" + }, + "description": "Get all transactions linked to a specific payout" + }, { "name": "date_from", "in": "query", @@ -18063,6 +18080,134 @@ } } }, + "/consumers/{consumer_id}/payment/payouts": { + "get": { + "tags": [ + "Payment", + "Payouts" + ], + "summary": "Retrieve all payouts", + "description": "Returns a list of payouts (periodic bank transfers made by the processor to the merchant).", + "operationId": "payment_get_payouts", + "security": [ + { + "mcp_auth": [ + "payment", + "payment.read", + "payment.payouts", + "payment.payouts.read" + ] + } + ], + "parameters": [ + { + "name": "consumer_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Consumer Id" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "default": 50, + "title": "Size" + }, + "description": "Page size" + }, + { + "name": "date_from", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Date From" + } + }, + { + "name": "date_to", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ], + "title": "Date To" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChiftPage_PayoutItemOut_" + } + } + } + }, + "400": { + "content": { + "application/json": { + "example": { + "message": "Error while trying to perform your request", + "status": "error" + }, + "schema": { + "$ref": "#/components/schemas/ChiftError" + } + } + }, + "description": "Bad Request" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/consumers/{consumer_id}/pms/orders": { "get": { "tags": [ @@ -24737,6 +24882,40 @@ ], "title": "ChiftPage[Payment]" }, + "ChiftPage_PayoutItemOut_": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/PayoutItemOut" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size" + ], + "title": "ChiftPage[PayoutItemOut]" + }, "ChiftPage_ProductCategoryItem_": { "properties": { "items": { @@ -40211,6 +40390,98 @@ ], "title": "PaymentTermAccountInfo" }, + "PayoutItemOut": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Technical id in Chift" + }, + "source_ref": { + "$ref": "#/components/schemas/Ref", + "description": "Technical id in the target software" + }, + "status": { + "$ref": "#/components/schemas/PayoutStatus", + "description": "Payout status" + }, + "type": { + "$ref": "#/components/schemas/PayoutType", + "description": "Payout type" + }, + "amount": { + "type": "number", + "title": "Amount", + "description": "Amount transferred to the merchant" + }, + "currency": { + "type": "string", + "title": "Currency", + "description": "Currency" + }, + "fee": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Fee", + "description": "Total fee applied by the processor" + }, + "extra_fee": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Extra Fee", + "description": "Extra fee, if exposed by the processor" + }, + "payment_date": { + "type": "string", + "format": "date", + "title": "Payment Date", + "description": "Date at which the payout was made" + } + }, + "type": "object", + "required": [ + "id", + "source_ref", + "status", + "type", + "amount", + "currency", + "payment_date" + ], + "title": "PayoutItemOut" + }, + "PayoutStatus": { + "type": "string", + "enum": [ + "scheduled", + "in_transit", + "paid", + "failed", + "canceled" + ], + "title": "PayoutStatus" + }, + "PayoutType": { + "type": "string", + "enum": [ + "payout", + "bank_account", + "other" + ], + "title": "PayoutType" + }, "PostAddressItem": { "properties": { "name": { diff --git a/chift/openapi/openapi.py b/chift/openapi/openapi.py index 43bd9b6..f50f057 100644 --- a/chift/openapi/openapi.py +++ b/chift/openapi/openapi.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: openapi.json -# timestamp: 2026-05-08T14:33:08+00:00 +# timestamp: 2026-05-15T09:15:13+00:00 from __future__ import annotations @@ -2728,6 +2728,20 @@ class PaymentTermAccountInfo(BaseModel): iban: str = Field(..., description="IBAN of the G or R account", title="Iban") +class PayoutStatus(Enum): + scheduled = "scheduled" + in_transit = "in_transit" + paid = "paid" + failed = "failed" + canceled = "canceled" + + +class PayoutType(Enum): + payout = "payout" + bank_account = "bank_account" + other = "other" + + class PostAddressItem(BaseModel): model_config = ConfigDict( extra="allow", @@ -6426,6 +6440,29 @@ class PaymentReporting(BaseModel): ) +class PayoutItemOut(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + id: str = Field(..., description="Technical id in Chift", title="Id") + source_ref: Ref = Field(..., description="Technical id in the target software") + status: PayoutStatus = Field(..., description="Payout status") + type: PayoutType = Field(..., description="Payout type") + amount: float = Field( + ..., description="Amount transferred to the merchant", title="Amount" + ) + currency: str = Field(..., description="Currency", title="Currency") + fee: Optional[float] = Field( + None, description="Total fee applied by the processor", title="Fee" + ) + extra_fee: Optional[float] = Field( + None, description="Extra fee, if exposed by the processor", title="Extra Fee" + ) + payment_date: Date = Field( + ..., description="Date at which the payout was made", title="Payment Date" + ) + + class PostSyncFlowEvent(BaseModel): model_config = ConfigDict( extra="allow", @@ -7330,6 +7367,16 @@ class ChiftPagePaymentMethodItem(BaseModel): size: conint(ge=1) = Field(..., title="Size") +class ChiftPagePayoutItemOut(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + items: List[PayoutItemOut] = Field(..., title="Items") + total: conint(ge=0) = Field(..., title="Total") + page: conint(ge=1) = Field(..., title="Page") + size: conint(ge=1) = Field(..., title="Size") + + class ChiftPageProductItemOut(BaseModel): model_config = ConfigDict( extra="allow", diff --git a/pyproject.toml b/pyproject.toml index 88aed4b..327a07d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "chift" -version = "0.6.0" +version = "0.6.1" description = "Chift API client" authors = ["Henry Hertoghe "] readme = "README.md" From 6610a9453d00377418a979d0198cb3fe4871b1c1 Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 18 May 2026 14:44:34 +0200 Subject: [PATCH 2/2] update --- chift/openapi/openapi.json | 21 +++++++++++++++++++++ chift/openapi/openapi.py | 28 +++++++++++++++++++--------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/chift/openapi/openapi.json b/chift/openapi/openapi.json index 820ab78..188b5c9 100644 --- a/chift/openapi/openapi.json +++ b/chift/openapi/openapi.json @@ -30402,6 +30402,18 @@ "type": "boolean", "title": "Optional", "default": false + }, + "visibility": { + "anyOf": [ + { + "$ref": "#/components/schemas/Visibility" + }, + { + "type": "null" + } + ], + "description": "Visibility of the credential. If connector is selected, it should be defined when the connector is activated on your environment. If consumer is selected, the end-user will have to provide the credential when creating the connection. If both is selected, the credential can be defined when the connector is activated on your environment or when the end-user creates the connection (it will not be available for the end-user when it's activated at connector-level)", + "default": "both" } }, "type": "object", @@ -44638,6 +44650,15 @@ ], "title": "VatCodeType" }, + "Visibility": { + "type": "string", + "enum": [ + "consumer", + "connector", + "both" + ], + "title": "Visibility" + }, "WebhookInstanceGetItem": { "properties": { "webhookid": { diff --git a/chift/openapi/openapi.py b/chift/openapi/openapi.py index f50f057..d538779 100644 --- a/chift/openapi/openapi.py +++ b/chift/openapi/openapi.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: openapi.json -# timestamp: 2026-05-15T09:15:13+00:00 +# timestamp: 2026-05-18T12:43:33+00:00 from __future__ import annotations @@ -1450,14 +1450,6 @@ class IntegationStatus(Enum): inactive = "inactive" -class IntegrationsCredentialItem(BaseModel): - model_config = ConfigDict( - extra="allow", - ) - name: str = Field(..., title="Name") - optional: Optional[bool] = Field(False, title="Optional") - - class IntegrationsPostConnectionItemConfig(BaseModel): model_config = ConfigDict( extra="allow", @@ -3530,6 +3522,12 @@ class VatCodeType(Enum): unknown = "unknown" +class Visibility(Enum): + consumer = "consumer" + connector = "connector" + both = "both" + + class WebhookInstanceGetItem(BaseModel): model_config = ConfigDict( extra="allow", @@ -5091,6 +5089,18 @@ class HTTPValidationError(BaseModel): detail: Optional[List[ValidationError]] = Field(None, title="Detail") +class IntegrationsCredentialItem(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + name: str = Field(..., title="Name") + optional: Optional[bool] = Field(False, title="Optional") + visibility: Optional[Visibility] = Field( + "both", + description="Visibility of the credential. If connector is selected, it should be defined when the connector is activated on your environment. If consumer is selected, the end-user will have to provide the credential when creating the connection. If both is selected, the credential can be defined when the connector is activated on your environment or when the end-user creates the connection (it will not be available for the end-user when it's activated at connector-level)", + ) + + class IntegrationsPostConnectionItem(BaseModel): model_config = ConfigDict( extra="allow",