Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
219 commits
Select commit Hold shift + click to select a range
a9dd9dc
bug patches
Feb 3, 2022
a07b7a4
fixed inheritence and changed pdf response to content
Feb 10, 2022
ef2c0d6
add auth user to sol prop
Feb 14, 2022
8994d13
added payment rejected event
Feb 17, 2022
d5c15b2
added auth users to individual customer dto
Feb 18, 2022
a20ad05
added nsf to ach return reasons
Feb 23, 2022
4bf5ad3
fixed transaction dto
Mar 3, 2022
28d0004
update
Mar 10, 2022
eabb243
bug patches
Feb 3, 2022
4a6771a
fixed inheritence and changed pdf response to content
Feb 10, 2022
86914a3
add auth user to sol prop
Feb 14, 2022
e1293d7
added payment rejected event
Feb 17, 2022
addd9bd
added auth users to individual customer dto
Feb 18, 2022
3652df2
added nsf to ach return reasons
Feb 23, 2022
1649093
fixed transaction dto
Mar 3, 2022
6d1dd08
update
Mar 10, 2022
ec014b3
merge conflicts
Mar 10, 2022
a82b783
added coded
Mar 10, 2022
517fb30
added codecs
Mar 10, 2022
2a8cfd1
coded update
Mar 10, 2022
4b89d13
adds support for /sandbox/applications/application_id/approve
Mar 18, 2022
e3b8a83
ApproveApplicationSBRequest
Mar 18, 2022
00de5d5
Merge pull request #1 from dragonprevost/application-approval-sim
avesk Mar 18, 2022
e4fd4c3
update to authorization requests
Mar 23, 2022
37dc174
card dto update
Mar 24, 2022
d047997
fix bug
Apr 1, 2022
6d99a25
added authorization canceled event
Apr 6, 2022
09d9aae
Adds support for simulating incoming ACH
Apr 6, 2022
a2ddb79
Merge pull request #2 from dragonprevost/simulate-incoming-ach
avesk Apr 6, 2022
32ca1a7
added limits to card create card request
Apr 7, 2022
ecfa4fe
Merge branch 'master' of github.com:dragonprevost/unit-python-sdk
Apr 7, 2022
8fdcc9a
card limits
Apr 8, 2022
b51dc56
patch card payload
Apr 11, 2022
ceb8c42
fix unit bug
Apr 12, 2022
7bca682
fix payment rejected type
Apr 22, 2022
8f90e12
PaymentCreated event returning Payment clearing event
Apr 22, 2022
a45ecfe
Merge pull request #3 from dragonprevost/fix-payment-rejected-event
avesk Apr 22, 2022
cf574d9
fix benificial owner bug
May 3, 2022
3513c59
Removes deprecated SSN field from card api
May 5, 2022
174b4eb
Merge pull request #4 from dragonprevost/remove-ssn-from-cards
avesk May 5, 2022
6dd43fc
bug patches
Feb 3, 2022
7604c3a
fixed inheritence and changed pdf response to content
Feb 10, 2022
f82564e
add auth user to sol prop
Feb 14, 2022
4b6f09c
added payment rejected event
Feb 17, 2022
1f8895d
added auth users to individual customer dto
Feb 18, 2022
86bb420
added nsf to ach return reasons
Feb 23, 2022
669d152
fixed transaction dto
Mar 3, 2022
b57a1ac
update
Mar 10, 2022
46f8605
added coded
Mar 10, 2022
4c1b769
added codecs
Mar 10, 2022
1a5fdbc
coded update
Mar 10, 2022
723e89a
adds support for /sandbox/applications/application_id/approve
Mar 18, 2022
93768ff
ApproveApplicationSBRequest
Mar 18, 2022
0b67831
update to authorization requests
Mar 23, 2022
5f115cd
card dto update
Mar 24, 2022
5c77ebb
fix bug
Apr 1, 2022
1c78ee1
added authorization canceled event
Apr 6, 2022
fd64f5d
added limits to card create card request
Apr 7, 2022
b394e8c
Adds support for simulating incoming ACH
Apr 6, 2022
6d87d0c
card limits
Apr 8, 2022
b160a0e
patch card payload
Apr 11, 2022
82f41cc
fix unit bug
Apr 12, 2022
129a913
fix payment rejected type
Apr 22, 2022
3d562a7
PaymentCreated event returning Payment clearing event
Apr 22, 2022
c913912
fix benificial owner bug
May 3, 2022
6670d91
created authorization declined event
May 10, 2022
dfddb0f
remove duplicate decoder
May 10, 2022
b2a008d
fix package
May 10, 2022
2e4a95d
fix func signature
May 10, 2022
62f6318
card authorization patches
May 30, 2022
cd2378f
fix merchant type bug
Jun 7, 2022
d363d96
added authorization canceled to coded
Jun 7, 2022
38c8208
fix coordinate bug
Jun 9, 2022
37da55f
added rewards to sdk
Jun 14, 2022
7246c06
reward patches
Jun 15, 2022
85af67b
reward bug fix
Jun 28, 2022
29feabe
fixed payment rejected bug
Jul 27, 2022
ce9b05a
fix customer updated codec bug
Jul 29, 2022
915e4d0
Patch CreateCounterpartyRequest to inherit UnitRequest
Sep 17, 2022
2ee62da
Merge pull request #5 from dragonprevost/patch-create-counterparty-re…
avesk Sep 17, 2022
cc30baa
Simulate transmitting and clearing ach payments
Jan 12, 2023
a4c63c2
Merge pull request #7 from MazumaGo/simulate-ach-payment-actions
avesk Jan 19, 2023
a3c64d0
Update CreateBusinessApplicationRequest with new required compliance …
Jun 13, 2023
4324dd4
Merge pull request #8 from MazumaGo/compliance-updates
eric-truss Jun 21, 2023
064660f
Add relevant models and operations for charge cards and repayments
Jul 7, 2023
dfbe4f7
Remove build/ folder and add to gitignore
Jul 11, 2023
a27740c
Minor fixes to charge cards
Jul 20, 2023
c997b22
simulate purchases
avesk Jul 20, 2023
2862234
Update objects with unit dto
Aug 3, 2023
a363368
Merge pull request #9 from MazumaGo/charge-cards
eric-truss Aug 3, 2023
88ad935
Add same day flag for ACH payments
Aug 4, 2023
fe3576c
Fix ordering of function parameters
Aug 5, 2023
c38cefa
Fix book payments
Aug 8, 2023
b0be3ff
Use keyword arg for same day to avoid errors
Aug 9, 2023
70cfa13
Merge remote-tracking branch 'origin/master' into simulate-purchasees
avesk Aug 11, 2023
8c7219e
replace sb_ with sandbox_ prefix
avesk Aug 16, 2023
330d08c
use merchant name
avesk Aug 16, 2023
784a526
Merge pull request #10 from MazumaGo/simulate-purchasees
avesk Aug 16, 2023
c13b1e7
Fix typo
Aug 17, 2023
d25d2dc
Add batch releases to Unit object
Aug 17, 2023
47333ce
rename
Aug 17, 2023
658772b
Fix purchaseTransactionDTO cardLast4Digits key error
avesk Aug 17, 2023
fde95ea
Merge pull request #11 from MazumaGo/fix-purchase-txn-dto
avesk Aug 17, 2023
dbe0074
Updates DTOs to accomodate purchase simulation responses
avesk Aug 17, 2023
eeb66c4
Merge pull request #12 from MazumaGo/fix-purchase-simulations
avesk Aug 17, 2023
5ce5391
fix error
Aug 21, 2023
0a1ce8a
Adds CheckDepositPendingReviewEvent and CheckDepositPendingEvent events
avesk Aug 22, 2023
ad4e0ae
Merge pull request #13 from MazumaGo/check-deposit-webhooks
avesk Aug 22, 2023
b734e22
fix issues
julia-truss Aug 23, 2023
aa59e84
Merge remote-tracking branch 'origin/master' into add-batch-release
julia-truss Aug 23, 2023
dbce57b
Merge pull request #14 from MazumaGo/add-batch-release
julia-truss Aug 24, 2023
bed432b
Check deposits
avesk Aug 28, 2023
9a018f1
Merge branch 'master' into check-deposits
avesk Aug 28, 2023
941f05d
Merge pull request #15 from MazumaGo/check-deposits
avesk Aug 28, 2023
40aa08f
Check deposit webhook updates
avesk Aug 29, 2023
6fd187d
updates
avesk Sep 8, 2023
79e2914
Merge pull request #16 from MazumaGo/check-deposit-webhook-updates
avesk Sep 8, 2023
671f7b4
Update codecs for Check Deposit Webhooks
avesk Sep 8, 2023
8b54bd6
Merge pull request #17 from MazumaGo/check-deposit-wh-codecs
avesk Sep 8, 2023
284716b
Fix previous status typo
Sep 14, 2023
586cb04
Add get_image
julia-truss Sep 20, 2023
767ecac
Merge pull request #18 from MazumaGo/get-check-deposit-image
mazumanick Sep 20, 2023
e24074d
Add account and routing numbers to ListCounterpartyParams
julia-truss Oct 30, 2023
5ee3a2b
Merge pull request #19 from MazumaGo/list-counterparty-ach-numbers
julia-truss Oct 31, 2023
ff57889
Category optional
Nov 13, 2023
bcfb024
Update purchase and merchant DTOs (#20)
julia-truss Feb 1, 2024
df9cb60
Fix KeyError when converting from json (#21)
julia-truss Feb 2, 2024
8dc3d7c
Account for incorrect merchant fields for simulations (#22)
julia-truss Feb 2, 2024
f3b7775
Response should output bytes (#23)
julia-truss Mar 1, 2024
6120e8d
astra pushToCard payment
avesk Mar 7, 2024
465e84f
revert inadvertant changes
avesk Mar 7, 2024
5ce31e0
Update title literal and individual application (#25)
julia-truss Mar 14, 2024
58aa3a2
pushToCardPayment on dto
avesk Mar 20, 2024
4e9899b
Fix payment dto
avesk Mar 20, 2024
aadbe7d
Merge pull request #24 from MazumaGo/astra-push-to-card
avesk Mar 21, 2024
eaef877
Update push to card request #26
julia-truss Mar 25, 2024
2a8470e
Add check payment resources
Mar 26, 2024
2dbfd38
Rename
Mar 26, 2024
5e752e1
Rename2
Mar 26, 2024
b12c980
Add check payments to client
Mar 26, 2024
915563f
Fix enums and add get endpoint for check payments
Mar 26, 2024
b716cc2
Add check payment transactions
Apr 8, 2024
ac8bc05
Add check payments to other references
Apr 8, 2024
8b9a8c0
Add create check payment
Apr 10, 2024
276b244
Include memo
Apr 10, 2024
0da1b2c
Remove item assignment
Apr 11, 2024
815e018
Add check payment counterparty to json encoder
Apr 12, 2024
04fda05
Remove counterpartyMoved param
Apr 12, 2024
4cad693
Add events (#27)
julia-truss Apr 18, 2024
190adab
Check payment codecs
avesk Apr 23, 2024
1531493
Cancel check payment and check stop payments (#28)
julia-truss Apr 23, 2024
bf7760d
Fix check payment event bugs (#29)
julia-truss Apr 24, 2024
0ac8f97
Fix key error on check payment processed event (#30)
julia-truss Apr 25, 2024
3effb89
Make check_number optional (#31)
julia-truss May 2, 2024
699e266
Add timeout handling to payment create
May 22, 2024
edf6072
Update application form version to V2024_06
avesk Jul 23, 2024
f8cda6f
Add patch check payment
Jul 23, 2024
78ecd3b
Remove version from application form create resource
avesk Jul 25, 2024
d74ad15
Adds pushToCardPayment codec
avesk Oct 10, 2024
fc68cf5
Merge pull request #33 from MazumaGo/add-push-to-card-codec
avesk Oct 10, 2024
813df60
Safe get on astraRoutineId
avesk Oct 10, 2024
5dafdfa
Merge pull request #34 from MazumaGo/add-push-to-card-codec
avesk Oct 10, 2024
2ff164a
Update officer dto and application literals (#35)
julia-truss Oct 21, 2024
64d7728
Update application request and beneficial owner (#36)
julia-truss Nov 1, 2024
5930419
Update customer and account dtos to faciliate archiving/closing (#37)
julia-truss Jan 10, 2025
e7e3543
Implements freeze account endpoint
avesk Jan 13, 2025
67f1886
fix reasonText
avesk Jan 14, 2025
c6b0ef7
Merge pull request #38 from MazumaGo/account-freeze
avesk Jan 14, 2025
0694c5f
add type creditAccountFreeze to freeze account request
avesk Jan 14, 2025
4a2500d
unfreeze account
avesk Jan 21, 2025
e5f863b
Merge pull request #39 from MazumaGo/unfreeze-account
avesk Jan 21, 2025
03d0e69
Add field to individual application dto (#40)
julia-truss Feb 25, 2025
ea28358
Add cancel for payments, return_check for check payments (#41)
julia-truss Apr 9, 2025
e97cbe8
feat(disputes): add dispute created event
samuelvasco May 12, 2025
366b1e3
feat(disputes): add status changed event
samuelvasco May 12, 2025
9fd9624
feat(disputes): add new events to codecs
samuelvasco May 13, 2025
f2b5830
ENG-1164: add dispute created event (#42)
samuelvasco May 13, 2025
47170f8
feat(disputes): api call to retrieve by id
samuelvasco May 14, 2025
51cd4e6
refactor: adapt get dispute endpoint to convention
samuelvasco May 16, 2025
a6b9659
ENG-1166: implement disputes api to retrieve by id #43
samuelvasco May 16, 2025
b37794f
feat: add events for account close
samuelvasco May 21, 2025
fe9abfe
Update returned object for from_json_api (#45)
julia-truss May 28, 2025
d07d041
refactor: remove unnecessary args from dto
samuelvasco May 29, 2025
95aeefe
Merge pull request #44 from MazumaGo/eng-1158-close-account-transactions
samuelvasco May 29, 2025
ef749f3
feat: add received payment marked for return event
samuelvasco Jun 10, 2025
0159679
feat: add reprocess fields and resources
samuelvasco Jun 11, 2025
995c133
refactor: rename ReceivedPaymentMarkedForReturn to ReceivedPaymentCre…
samuelvasco Jun 11, 2025
16520ea
fix: optional fields on received payment created event
samuelvasco Jun 16, 2025
d6993ce
Merge pull request #46 from MazumaGo/eng-1335-handle-receivedpaymentm…
samuelvasco Jul 3, 2025
f4ae236
Update access for attributes for AuthorizationRequestDeclinedEvent (#47)
julia-truss Jul 18, 2025
d1aa75e
feat: add jwt subject to authorized user entity
samuelvasco Jul 22, 2025
ed366d2
feat: add optional jwt_token field to CreateCustomerToken DTO
samuelvasco Jul 23, 2025
4e56161
feat: make jwtSubject field optional in authorized user serialization
samuelvasco Jul 23, 2025
a0cdf13
Merge pull request #48 from MazumaGo/eng-1456-unit_create_customer_to…
avesk Jul 30, 2025
caefec6
feat: add card fraud case event models
in2q Aug 4, 2025
959a163
Nixed punctuation, updated to proper event names.
in2q Aug 7, 2025
671bbb2
Merge pull request #49 from MazumaGo/fraud-case-events
in2q Aug 8, 2025
7c4c0da
Add operating address to application dtos (#51)
julia-truss Oct 20, 2025
17f8bc5
Remove operatingAddress from individual applications (#52)
julia-truss Oct 21, 2025
10ac731
applications/check-registered-agent-address
avesk Oct 22, 2025
2298c92
remove unused code
avesk Oct 22, 2025
c286167
Remove blank space
avesk Oct 22, 2025
b7c1903
MR Feedback
avesk Oct 22, 2025
3f02a89
Fix type
avesk Oct 22, 2025
5b7d74f
Inherit request
avesk Oct 22, 2025
d010935
Fix attrs
avesk Oct 22, 2025
feb0b1d
Merge pull request #53 from MazumaGo/eng-2507-update-unit-sdk-to-supp…
avesk Oct 22, 2025
005039d
feat: add idempotency key to create business applications
samuelvasco Oct 27, 2025
82c780a
Merge pull request #54 from MazumaGo/eng-2499-use-idempotency-key-whe…
samuelvasco Oct 28, 2025
435fede
Handle absent merchants in adjustment transactions
avesk Oct 30, 2025
bfab114
Revert sources/package info changes
avesk Oct 30, 2025
f21ecfa
Merge pull request #55 from MazumaGo/hotfix-adjustment-txns
avesk Oct 31, 2025
510df64
Define write off transaction dto (#56)
julia-truss Nov 13, 2025
7cfb15d
Include writeoffs in transaction dto (#57)
julia-truss Nov 17, 2025
67133c6
ENG-2874: add date filters to list events (#58)
samuelvasco Dec 1, 2025
7034bdd
Expose interest earnings in Unit SDK (#60)
ben-wolfe Feb 25, 2026
0390fb5
ENG-3084: add payment canceled event (#59)
samuelvasco Feb 26, 2026
fcaf834
Cursor skill update
avesk Mar 2, 2026
d2883cc
fix: make traceNumber and secCode optional in ReceivedPaymentCreatedE…
avesk Mar 5, 2026
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
34 changes: 34 additions & 0 deletions .cursor/rules/python-sdk.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
alwaysApply: true
description: Coding conventions for the Unit Python SDK fork
---

## Unit Python SDK Conventions

This is a fork of the Unit.co Python SDK. Follow the same Python style conventions as the API repo (keyword arguments, no docstrings, comments explain why not what).

### Request Types

- Every request type must implement `to_json_api()` returning a JSON API payload (`{"data": {"type": "...", "attributes": {...}}}`)
- Use keyword arguments in constructors
- Optional fields should default to `None` and be excluded from the serialized payload when not set

### DTO Types

- DTOs are response types instantiated by `DtoDecoder.decode()` from JSON API responses
- Each DTO has an `id` and an `attributes` dict
- DTOs are dataclass-style objects (plain `__init__` with attribute assignment)

### Codec Registration

When adding a new Unit API type:
1. Create the DTO class in `unit/models/`
2. Create the request class with `to_json_api()` in the same file
3. Add the JSON API type string -> DTO class mapping to `mappings` in `unit/models/codecs.py`
4. Add resource methods in `unit/api/` if needed

### Resource Classes

- All resource classes inherit from `BaseResource` (`unit/api/base_resource.py`)
- Use `self._post()`, `self._get()`, `self._patch()` etc. from BaseResource
- Resource methods return `UnitResponse` wrapper objects
14 changes: 14 additions & 0 deletions .cursor/skills/local-install/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
name: truss-unit-sdk-local-install
description: Install the local unit-python-sdk fork into the API virtualenv in editable mode so SDK changes are immediately reflected. Use when modifying unit-python-sdk, adding new SDK types, or after any edit to unit-python-sdk/unit/models/ that needs to be picked up by the API.
---

# Truss Unit SDK Local Install

After modifying anything in `unit-python-sdk/`, run this to make the API venv pick up the changes:

```bash
/Users/averykushner/cursor-projects/truss-fullstack/api/.venv/bin/pip install -e /Users/averykushner/cursor-projects/truss-fullstack/unit-python-sdk
```

The `-e` flag installs in editable mode — the venv symlinks to the local source, so subsequent edits to the SDK are reflected immediately without reinstalling. Only run this command again if the venv is recreated or the SDK package metadata changes (e.g. `pyproject.toml`).
281 changes: 281 additions & 0 deletions .cursor/skills/sdk-guide/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
---
name: truss-unit-sdk
description: Guide to the Truss Unit Python SDK fork covering the resource-based API pattern, application DTOs and request types, JSON API codec system, and how the API repo interfaces with the SDK via unit_api_call. Use when updating the Unit SDK, adding new SDK types, modifying application submission, working with Unit API responses, or preparing for Unit API version migrations.
---

# Truss Unit Python SDK

## Overview

Truss maintains a fork of the Unit Python SDK at `unit-python-sdk/`. This is a typed REST client for the [Unit.co](https://www.unit.co) banking API. The Truss API repo (`api/`) imports this SDK and wraps all calls through `unit_api_call()`.

## Project Structure

```
unit-python-sdk/
├── unit/
│ ├── __init__.py # Unit client class — exposes resource accessors
│ ├── api/ # Resource classes (REST endpoint wrappers)
│ │ ├── base_resource.py # HTTP methods, auth headers, JSON API encoding
│ │ ├── application_resource.py # applications.create(), .get(), .list(), .update()
│ │ └── [30+ other resources] # payments, accounts, customers, etc.
│ ├── models/ # DTOs, request types, response types
│ │ ├── application.py # Application DTOs + Create/Update request types
│ │ ├── codecs.py # DtoDecoder — JSON API type → DTO class mapping
│ │ └── [30+ other model files]
│ └── utils/ # Utility functions
├── e2e_tests/
│ └── application_test.py # Application e2e tests
└── setup.py # Package version (currently 0.10.5)
```

## SDK Architecture

### Request → API → Response Flow

```
1. Build Request Object (e.g., CreateBusinessApplicationRequest)
↓ .to_json_api()
2. JSON API Payload {"data": {"type": "businessApplication", "attributes": {...}}}
↓ BaseResource.post(url, payload)
3. HTTP POST POST {api_url}/applications
│ Headers: Content-Type: application/vnd.api+json
│ Authorization: Bearer {token}
4. Raw JSON Response {"data": {"type": "businessApplication", "id": "...", "attributes": {...}}}
↓ DtoDecoder.decode(response)
5. Typed DTO BusinessApplicationDTO(id=..., attributes=...)
↓ UnitResponse(data=dto, included=[...])
6. UnitResponse Wrapper Final response with typed data + included resources
```

### BaseResource (`unit/api/base_resource.py`)

All resource classes inherit from `BaseResource`. It provides:

- `get(url)`, `post(url, data)`, `patch(url, data)`, `put(url, data)`, `delete(url)`
- Sets `Content-Type: application/vnd.api+json` and `Authorization: Bearer {token}`
- Serializes request objects via `UnitEncoder` (handles `to_json_api()` on request objects)
- Returns raw response dict for decoding

### Unit Client (`unit/__init__.py`)

The main `Unit` class instantiates all resource accessors:

```python
class Unit:
def __init__(self, api_url, token):
self.applications = ApplicationResource(api_url, token)
self.payments = PaymentResource(api_url, token)
self.accounts = AccountResource(api_url, token)
# ... 30+ more resources
```

## Application Types

### DTOs (Response Types)

| Class | JSON API Type | Description |
|-------|---------------|-------------|
| `IndividualApplicationDTO` | `"individualApplication"` | Individual/sole prop application (includes `sole_proprietorship` flag) |
| `BusinessApplicationDTO` | `"businessApplication"` | Business application |

Both are dataclass-style objects with an `id` (Unit's application ID) and `attributes` dict containing all application fields.

### Request Types

| Class | Creates | Key Fields |
|-------|---------|------------|
| `CreateIndividualApplicationRequest` | Individual application | full_name, dob, address, email, phone, ssn, sole_proprietorship, ip, tags, idempotency_key |
| `CreateBusinessApplicationRequest` | Business application | name, address, phone, ein, entity_type, state_of_incorporation, contact, officer, beneficial_owners, tags, idempotency_key |

### Sole Prop as Individual

Sole proprietorships are **not** a separate type. They use `CreateIndividualApplicationRequest` with `sole_proprietorship=True` and additional business-related fields:

```python
CreateIndividualApplicationRequest(
full_name=FullName(first="John", last="Doe"),
sole_proprietorship=True,
# ... individual fields plus business fields
)
```

### `to_json_api()` — Serialization

Each request type implements `to_json_api()` which returns the JSON API payload:

```python
def to_json_api(self):
return {
"data": {
"type": "individualApplication", # or "businessApplication"
"attributes": {
# All fields serialized here
}
}
}
```

This is called automatically by `UnitEncoder` during serialization in `BaseResource.post()`.

## Codec System (`unit/models/codecs.py`)

### Type Mapping

`DtoDecoder.decode()` uses a `mappings` dict to route JSON API responses to the correct DTO class:

```python
mappings = {
"individualApplication": IndividualApplicationDTO,
"businessApplication": BusinessApplicationDTO,
# ... 50+ other type mappings
}
```

When a response comes back with `"type": "businessApplication"`, the decoder instantiates `BusinessApplicationDTO` with the response data.

### Adding New Types

To support a new Unit API type:

1. Create the DTO class in the appropriate `unit/models/*.py` file
2. Create the request class with `to_json_api()` method
3. Add the type string → DTO class mapping to `mappings` in `unit/models/codecs.py`
4. If needed, add a new resource method or resource class in `unit/api/`

## Sub-types Used in Applications

### FullName
```python
FullName(first="John", last="Doe")
```

### Phone
```python
Phone(country_code="1", number="5551234567")
```

### Address (UnitAddress in Truss API)
```python
Address(street="123 Main St", city="Austin", state="TX", postal_code="78701", country="US")
```

### Officer
```python
Officer(
full_name=FullName(...),
date_of_birth=date(...),
address=Address(...),
phone=Phone(...),
email="...",
ssn="...", # or passport/nationality for non-US
title="CEO",
)
```

### BeneficialOwner
```python
BeneficialOwner(
full_name=FullName(...),
date_of_birth=date(...),
address=Address(...),
phone=Phone(...),
email="...",
ssn="...",
percentage=50, # 25-100
)
```

### BusinessContact
```python
BusinessContact(
full_name=FullName(...),
phone=Phone(...),
email="...",
)
```

## How the API Repo Interfaces with the SDK

For the `unit_api_call()` wrapper pattern, error mapping, and client initialization details, see the `architecture` skill at `api/.cursor/skills/architecture/SKILL.md`.

### Model-to-SDK Conversion

The conversion from Django models to SDK request types happens in `api/src/api/operations/account/onboarding/application/submit_onboarding_application.py`. See the `truss-onboarding-architecture` skill for the complete field mapping.

## Subagents

### trace-sdk-application-types: Map SDK application types and fields

**Type:** `explore`
**Model:** *(default)*
**When:** You need to understand the complete structure of Unit SDK application types — every field, sub-type, and serialization detail — typically before modifying the SDK for a new Unit API version.

**Prompt:**

> Map the complete structure of application types in the Truss Unit Python SDK fork at `unit-python-sdk/`.
>
> 1. **Request types**: Read `unit-python-sdk/unit/models/application.py`. For each request class (`CreateIndividualApplicationRequest`, `CreateBusinessApplicationRequest`):
> - Document every field with its type and whether it's required or optional
> - Read the `to_json_api()` method to understand exactly how each field is serialized
> - Note any conditional fields (e.g., sole_proprietorship flag changes which fields are included)
>
> 2. **DTO types**: In the same file, read `IndividualApplicationDTO` and `BusinessApplicationDTO`:
> - Document the response structure (id, type, attributes)
> - Document how the DTO is constructed from JSON API responses
>
> 3. **Sub-types**: Find and read the definitions of `FullName`, `Phone`, `Address`, `Officer`, `BeneficialOwner`, `BusinessContact`. These may be in `unit/models/application.py` or imported from other model files. Document their fields.
>
> 4. **Codec mapping**: Read `unit-python-sdk/unit/models/codecs.py`:
> - Find the `mappings` dict
> - Document which type strings map to which DTO classes for applications
> - Understand how `DtoDecoder.decode()` routes responses
>
> 5. **Resource methods**: Read `unit-python-sdk/unit/api/application_resource.py`:
> - Document each method (create, get, list, update, upload, approve_sb)
> - Note the URL patterns used for each method
> - Document return types
>
> Return:
> - Complete field schema for each request type (field name, type, required/optional, serialized JSON key)
> - Complete field schema for each DTO type
> - Sub-type field schemas
> - Codec type string → class mapping for applications
> - Resource method signatures and URL patterns

### audit-sdk-for-v2-migration: Identify SDK changes needed for Unit API v2

**Type:** `explore`
**Model:** *(default)*
**When:** You are preparing to update the Unit SDK fork to support a new version of the Unit applications API and need to identify what must change.

**Prompt:**

> Audit the Truss Unit Python SDK fork for changes needed to support Unit Applications API v2. The SDK is at `unit-python-sdk/`.
>
> 1. **Current application code**: Read these files completely:
> - `unit-python-sdk/unit/models/application.py` — all DTOs and request types
> - `unit-python-sdk/unit/api/application_resource.py` — all API methods
> - `unit-python-sdk/unit/models/codecs.py` — type mappings
> - `unit-python-sdk/unit/__init__.py` — client resource initialization
>
> 2. **SDK patterns for other resources**: Read 2-3 other resource/model pairs to understand how the SDK handles different resource types. This helps identify reusable patterns:
> - Pick resources that have complex nested types (like `payment.py` or `account.py`)
>
> 3. **Test patterns**: Read `unit-python-sdk/e2e_tests/application_test.py` to understand how application tests are structured.
>
> 4. **How the API repo consumes the SDK**: Read these files to understand what the API repo depends on:
> - `api/src/api/operations/account/onboarding/application/submit_onboarding_application.py`
> - `api/src/api/utils/integrations/unit/unit.py` (unit_api_call wrapper)
>
> Return:
> - List of files that need modification
> - For each file, what specifically needs to change (new classes, modified methods, new mappings)
> - Backward compatibility concerns (can v1 and v2 coexist?)
> - Recommended approach: separate v2 classes vs. version parameter vs. extending existing classes
> - API repo callsites that reference SDK types and would need updating
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ venv/*
dist/

.DS_Store

build/
22 changes: 22 additions & 0 deletions unit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
from unit.api.application_resource import ApplicationResource
from unit.api.check_deposit_resource import CheckDepositResource
from unit.api.batch_release_resource import BatchReleaseResource
from unit.api.check_payment_resource import CheckPaymentResource
from unit.api.check_stop_payment_resource import CheckStopPaymentResource
from unit.api.customer_resource import CustomerResource
from unit.api.account_resource import AccountResource
from unit.api.card_resource import CardResource
from unit.api.transaction_resource import TransactionResource
from unit.api.payment_resource import PaymentResource
from unit.api.repayment_resource import RepaymentResource
from unit.api.ach_resource import AchResource
from unit.api.statement_resource import StatementResource
from unit.api.customerToken_resource import CustomerTokenResource
from unit.api.counterparty_resource import CounterpartyResource
Expand All @@ -19,6 +25,11 @@
from unit.api.authorization_resource import AuthorizationResource
from unit.api.authorization_request_resource import AuthorizationRequestResource
from unit.api.account_end_of_day_resource import AccountEndOfDayResource
from unit.api.accrued_interest_resource import AccruedInterestResource
from unit.api.reward_resource import RewardResource
from unit.api.dispute_resource import DisputeResource
from unit.api.received_payment_resource import ReceivedPaymentResource
from unit.api.check_registered_address import CheckRegisteredAddressResource

__all__ = ["api", "models", "utils"]

Expand All @@ -31,6 +42,9 @@ def __init__(self, api_url, token):
self.cards = CardResource(api_url, token)
self.transactions = TransactionResource(api_url, token)
self.payments = PaymentResource(api_url, token)
self.check_deposits = CheckDepositResource(api_url, token)
self.repayments = RepaymentResource(api_url, token)
self.ach = AchResource(api_url, token)
self.statements = StatementResource(api_url, token)
self.customerTokens = CustomerTokenResource(api_url, token)
self.counterparty = CounterpartyResource(api_url, token)
Expand All @@ -46,3 +60,11 @@ def __init__(self, api_url, token):
self.authorizations = AuthorizationResource(api_url, token)
self.authorization_requests = AuthorizationRequestResource(api_url, token)
self.account_end_of_day = AccountEndOfDayResource(api_url, token)
self.accrued_interest = AccruedInterestResource(api_url, token)
self.rewards = RewardResource(api_url, token)
self.batchRelease = BatchReleaseResource(api_url, token)
self.check_payments = CheckPaymentResource(api_url, token)
self.check_stop_payments = CheckStopPaymentResource(api_url, token)
self.disputes = DisputeResource(api_url, token)
self.received_payments = ReceivedPaymentResource(api_url, token)
self.check_registered_address = CheckRegisteredAddressResource(api_url, token)
Loading