prava-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. prava_sdk-0.1.0/.gitignore +12 -0
  2. prava_sdk-0.1.0/LICENSE +21 -0
  3. prava_sdk-0.1.0/PKG-INFO +236 -0
  4. prava_sdk-0.1.0/README.md +180 -0
  5. prava_sdk-0.1.0/docs/architecture.md +44 -0
  6. prava_sdk-0.1.0/docs/assets/prava-payments-logo.svg +4 -0
  7. prava_sdk-0.1.0/docs/examples.md +31 -0
  8. prava_sdk-0.1.0/docs/getting-started.md +67 -0
  9. prava_sdk-0.1.0/docs/guides/async.md +50 -0
  10. prava_sdk-0.1.0/docs/guides/cards.md +49 -0
  11. prava_sdk-0.1.0/docs/guides/payment-flow.md +128 -0
  12. prava_sdk-0.1.0/docs/index.md +3 -0
  13. prava_sdk-0.1.0/docs/javascripts/site.js +84 -0
  14. prava_sdk-0.1.0/docs/reference/client.md +48 -0
  15. prava_sdk-0.1.0/docs/reference/errors.md +45 -0
  16. prava_sdk-0.1.0/docs/reference/models.md +57 -0
  17. prava_sdk-0.1.0/docs/security.md +32 -0
  18. prava_sdk-0.1.0/docs/stylesheets/extra.css +1697 -0
  19. prava_sdk-0.1.0/examples/__init__.py +1 -0
  20. prava_sdk-0.1.0/examples/async_payment_flow.py +71 -0
  21. prava_sdk-0.1.0/examples/complete_payment.py +91 -0
  22. prava_sdk-0.1.0/examples/create_embedded_session.py +73 -0
  23. prava_sdk-0.1.0/examples/create_hosted_session.py +73 -0
  24. prava_sdk-0.1.0/examples/manage_cards.py +48 -0
  25. prava_sdk-0.1.0/mkdocs.yml +52 -0
  26. prava_sdk-0.1.0/pyproject.toml +88 -0
  27. prava_sdk-0.1.0/src/prava_sdk/__init__.py +94 -0
  28. prava_sdk-0.1.0/src/prava_sdk/_config.py +91 -0
  29. prava_sdk-0.1.0/src/prava_sdk/_transport.py +176 -0
  30. prava_sdk-0.1.0/src/prava_sdk/_version.py +1 -0
  31. prava_sdk-0.1.0/src/prava_sdk/client.py +116 -0
  32. prava_sdk-0.1.0/src/prava_sdk/errors.py +134 -0
  33. prava_sdk-0.1.0/src/prava_sdk/models/__init__.py +71 -0
  34. prava_sdk-0.1.0/src/prava_sdk/models/_base.py +66 -0
  35. prava_sdk-0.1.0/src/prava_sdk/models/cards.py +72 -0
  36. prava_sdk-0.1.0/src/prava_sdk/models/enums.py +58 -0
  37. prava_sdk-0.1.0/src/prava_sdk/models/sessions.py +162 -0
  38. prava_sdk-0.1.0/src/prava_sdk/py.typed +1 -0
  39. prava_sdk-0.1.0/src/prava_sdk/resources/__init__.py +11 -0
  40. prava_sdk-0.1.0/src/prava_sdk/resources/_base.py +101 -0
  41. prava_sdk-0.1.0/src/prava_sdk/resources/cards.py +124 -0
  42. prava_sdk-0.1.0/src/prava_sdk/resources/sessions.py +314 -0
  43. prava_sdk-0.1.0/tests/__init__.py +1 -0
  44. prava_sdk-0.1.0/tests/conftest.py +104 -0
  45. prava_sdk-0.1.0/tests/test_async_client.py +141 -0
  46. prava_sdk-0.1.0/tests/test_client.py +329 -0
  47. prava_sdk-0.1.0/tests/test_examples.py +16 -0
  48. prava_sdk-0.1.0/tests/test_models.py +128 -0
  49. prava_sdk-0.1.0/uv.lock +1038 -0
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .coverage
5
+ .mypy_cache/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .venv/
9
+ node_modules/
10
+ build/
11
+ dist/
12
+ site/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Prava Payments
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: prava-sdk
3
+ Version: 0.1.0
4
+ Summary: Official Python server-side SDK for Prava Payments
5
+ Project-URL: Documentation, https://prava-sdk.prajwalsuryawanshi.in
6
+ Project-URL: Homepage, https://www.prava.space
7
+ Project-URL: Issues, https://github.com/prajwalsuryawanshi/prava-payments/issues
8
+ Project-URL: Source, https://github.com/prajwalsuryawanshi/prava-payments
9
+ Author-email: Prava Payments <support@prava.space>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Prava Payments
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: agentic-commerce,payments,prava,sdk
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Operating System :: OS Independent
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Typing :: Typed
43
+ Requires-Python: >=3.10
44
+ Requires-Dist: httpx<1,>=0.27
45
+ Requires-Dist: pydantic[email]<3,>=2.7
46
+ Provides-Extra: dev
47
+ Requires-Dist: build!=1.5.1,<2,>=1.2; extra == 'dev'
48
+ Requires-Dist: hatchling<2,>=1.25; extra == 'dev'
49
+ Requires-Dist: mkdocs<2,>=1.6; extra == 'dev'
50
+ Requires-Dist: mypy<2,>=1.11; extra == 'dev'
51
+ Requires-Dist: pytest-asyncio<2,>=0.24; extra == 'dev'
52
+ Requires-Dist: pytest<10,>=8; extra == 'dev'
53
+ Requires-Dist: respx<1,>=0.21; extra == 'dev'
54
+ Requires-Dist: ruff<1,>=0.6; extra == 'dev'
55
+ Description-Content-Type: text/markdown
56
+
57
+ # Prava Python SDK
58
+
59
+ Typed server-side Python SDK for [Prava Payments](https://www.prava.space).
60
+
61
+ [Documentation](https://prava-sdk.prajwalsuryawanshi.in) ·
62
+ [Source](https://github.com/prajwalsuryawanshi/prava-payments)
63
+
64
+ The SDK creates payment sessions, manages enrolled cards, retrieves one-time payment
65
+ credentials, and reports checkout outcomes. Card collection still happens on Prava's hosted
66
+ surface or through the browser [`@prava-sdk/core`](https://www.npmjs.com/package/@prava-sdk/core)
67
+ package—your Python server must never collect a cardholder's raw card number.
68
+
69
+ ## Installation
70
+
71
+ ```bash
72
+ pip install prava-sdk
73
+ ```
74
+
75
+ Python 3.10 or newer is required.
76
+
77
+ The complete SDK guide is available in [docs/](docs/index.md), with runnable programs in
78
+ [examples/](examples/).
79
+
80
+ ## Quick start
81
+
82
+ ```python
83
+ from decimal import Decimal
84
+
85
+ from prava_sdk import PravaClient
86
+
87
+ client = PravaClient("sk_test_xxx")
88
+
89
+ session = client.sessions.create(
90
+ user_id="user_123",
91
+ user_email="buyer@example.com",
92
+ total_amount=Decimal("49.99"),
93
+ currency="USD",
94
+ purchase_context=[
95
+ {
96
+ "merchant_details": {
97
+ "name": "Example Store",
98
+ "url": "https://merchant.example",
99
+ "country_code_iso2": "US",
100
+ },
101
+ "product_details": [
102
+ {
103
+ "description": "Example product",
104
+ "unit_price": "49.99",
105
+ "product_id": "sku_123",
106
+ "quantity": 1,
107
+ }
108
+ ],
109
+ }
110
+ ],
111
+ integration_type="full_checkout",
112
+ callback_url="https://app.example/payments/complete",
113
+ )
114
+
115
+ # Send the cardholder to session.iframe_url. After card entry and passkey approval:
116
+ result = client.sessions.wait_for_payment_result(session.session_id)
117
+ line_item = result.transactions[0].line_items[0]
118
+
119
+ card_number = line_item.token.get_secret_value() if line_item.token else None
120
+ dynamic_cvv = line_item.dynamic_cvv.get_secret_value() if line_item.dynamic_cvv else None
121
+
122
+ # Use the one-time credentials at the merchant checkout, then always report the outcome.
123
+ client.sessions.report_status(
124
+ session.session_id,
125
+ txn_ref_id=line_item.txn_ref_id,
126
+ txn_status="APPROVED",
127
+ )
128
+
129
+ client.close()
130
+ ```
131
+
132
+ The secret key can instead be supplied through `PRAVA_SECRET_KEY`. `sk_test_*` keys automatically
133
+ use `https://sandbox.api.prava.space`; `sk_live_*` keys use `https://api.prava.space`.
134
+
135
+ Use the client as a context manager to guarantee cleanup:
136
+
137
+ ```python
138
+ from prava_sdk import PravaClient
139
+
140
+ with PravaClient("sk_test_xxx") as client:
141
+ cards = client.cards.list(customer_id="user_123")
142
+ ```
143
+
144
+ ## Async client
145
+
146
+ `AsyncPravaClient` exposes the same grouped resources and method arguments:
147
+
148
+ ```python
149
+ from prava_sdk import AsyncPravaClient
150
+
151
+ async with AsyncPravaClient("sk_test_xxx") as client:
152
+ result = await client.sessions.wait_for_payment_result(
153
+ "ses_123",
154
+ timeout=300,
155
+ poll_interval=2,
156
+ )
157
+ ```
158
+
159
+ ## API
160
+
161
+ ### Sessions
162
+
163
+ - `client.sessions.create(...)`
164
+ - `client.sessions.revoke(session_id)`
165
+ - `client.sessions.get_payment_result(session_id)`
166
+ - `client.sessions.wait_for_payment_result(session_id, timeout=300, poll_interval=2)`
167
+ - `client.sessions.report_status(session_id, ...)`
168
+
169
+ The polling helper returns as soon as the result status becomes `awaiting_result`, `completed`, or
170
+ `failed`. It raises `PravaPollingTimeoutError` if the session remains `pending` past the timeout.
171
+
172
+ ### Cards
173
+
174
+ - `client.cards.list(customer_id=..., status="active", include_card_art=False)`
175
+ - `client.cards.delete(customer_id=..., card_id=..., reason="OTHER")`
176
+
177
+ Only non-sensitive card metadata is returned by card-management endpoints.
178
+
179
+ ## Errors
180
+
181
+ All failures derive from `PravaError`. API exceptions expose `code`, `message`, `status_code`,
182
+ `details`, and `response_id` (from the `X-Response-ID` response header):
183
+
184
+ ```python
185
+ from prava_sdk import PravaError
186
+
187
+ try:
188
+ client.sessions.revoke("ses_missing")
189
+ except PravaError as exc:
190
+ print(exc.code, exc.response_id)
191
+ ```
192
+
193
+ The SDK provides dedicated authentication, validation, not-found, invalid-state, rate-limit,
194
+ transport, request-timeout, and polling-timeout exception types. Requests are not retried
195
+ automatically because the API does not currently document idempotency keys.
196
+
197
+ ## Security
198
+
199
+ - Never use `sk_test_*` or `sk_live_*` keys in browsers, mobile apps, logs, or version control.
200
+ - Never collect or send a cardholder's underlying card number through this SDK.
201
+ - Payment-result `token` and `dynamic_cvv` values are Pydantic `SecretStr` fields and are redacted
202
+ from normal model representations. Retrieve them only immediately before checkout.
203
+ - Always call `report_status` with `APPROVED` or `DECLINED` after attempting checkout.
204
+
205
+ See the [API reference](https://docs.prava.space/api-reference/overview),
206
+ [error catalog](https://docs.prava.space/api-reference/errors), and
207
+ [sandbox guide](https://docs.prava.space/api-reference/testing) for the complete server contract.
208
+
209
+ ## Package architecture
210
+
211
+ The SDK is organized as a standalone Python library:
212
+
213
+ ```text
214
+ prava_sdk/
215
+ ├── client.py # Small public sync and async client facades
216
+ ├── resources/ # Session and card endpoint groups
217
+ │ └── _base.py # Shared resource contracts and validation boundary
218
+ ├── models/ # Pydantic requests, responses, and enums
219
+ ├── _config.py # Secret-key and environment resolution
220
+ ├── _transport.py # Shared HTTP, JSON, and response handling
221
+ └── errors.py # Public exception hierarchy
222
+ ```
223
+
224
+ The JavaScript SDK is not a runtime or build dependency. It only handles browser-side card
225
+ collection and is excluded from Python source and wheel distributions.
226
+
227
+ ## Development
228
+
229
+ ```bash
230
+ uv sync --extra dev
231
+ uv run ruff check .
232
+ uv run mypy
233
+ uv run pytest
234
+ uv run mkdocs build --strict
235
+ uv run python -m build
236
+ ```
@@ -0,0 +1,180 @@
1
+ # Prava Python SDK
2
+
3
+ Typed server-side Python SDK for [Prava Payments](https://www.prava.space).
4
+
5
+ [Documentation](https://prava-sdk.prajwalsuryawanshi.in) ·
6
+ [Source](https://github.com/prajwalsuryawanshi/prava-payments)
7
+
8
+ The SDK creates payment sessions, manages enrolled cards, retrieves one-time payment
9
+ credentials, and reports checkout outcomes. Card collection still happens on Prava's hosted
10
+ surface or through the browser [`@prava-sdk/core`](https://www.npmjs.com/package/@prava-sdk/core)
11
+ package—your Python server must never collect a cardholder's raw card number.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pip install prava-sdk
17
+ ```
18
+
19
+ Python 3.10 or newer is required.
20
+
21
+ The complete SDK guide is available in [docs/](docs/index.md), with runnable programs in
22
+ [examples/](examples/).
23
+
24
+ ## Quick start
25
+
26
+ ```python
27
+ from decimal import Decimal
28
+
29
+ from prava_sdk import PravaClient
30
+
31
+ client = PravaClient("sk_test_xxx")
32
+
33
+ session = client.sessions.create(
34
+ user_id="user_123",
35
+ user_email="buyer@example.com",
36
+ total_amount=Decimal("49.99"),
37
+ currency="USD",
38
+ purchase_context=[
39
+ {
40
+ "merchant_details": {
41
+ "name": "Example Store",
42
+ "url": "https://merchant.example",
43
+ "country_code_iso2": "US",
44
+ },
45
+ "product_details": [
46
+ {
47
+ "description": "Example product",
48
+ "unit_price": "49.99",
49
+ "product_id": "sku_123",
50
+ "quantity": 1,
51
+ }
52
+ ],
53
+ }
54
+ ],
55
+ integration_type="full_checkout",
56
+ callback_url="https://app.example/payments/complete",
57
+ )
58
+
59
+ # Send the cardholder to session.iframe_url. After card entry and passkey approval:
60
+ result = client.sessions.wait_for_payment_result(session.session_id)
61
+ line_item = result.transactions[0].line_items[0]
62
+
63
+ card_number = line_item.token.get_secret_value() if line_item.token else None
64
+ dynamic_cvv = line_item.dynamic_cvv.get_secret_value() if line_item.dynamic_cvv else None
65
+
66
+ # Use the one-time credentials at the merchant checkout, then always report the outcome.
67
+ client.sessions.report_status(
68
+ session.session_id,
69
+ txn_ref_id=line_item.txn_ref_id,
70
+ txn_status="APPROVED",
71
+ )
72
+
73
+ client.close()
74
+ ```
75
+
76
+ The secret key can instead be supplied through `PRAVA_SECRET_KEY`. `sk_test_*` keys automatically
77
+ use `https://sandbox.api.prava.space`; `sk_live_*` keys use `https://api.prava.space`.
78
+
79
+ Use the client as a context manager to guarantee cleanup:
80
+
81
+ ```python
82
+ from prava_sdk import PravaClient
83
+
84
+ with PravaClient("sk_test_xxx") as client:
85
+ cards = client.cards.list(customer_id="user_123")
86
+ ```
87
+
88
+ ## Async client
89
+
90
+ `AsyncPravaClient` exposes the same grouped resources and method arguments:
91
+
92
+ ```python
93
+ from prava_sdk import AsyncPravaClient
94
+
95
+ async with AsyncPravaClient("sk_test_xxx") as client:
96
+ result = await client.sessions.wait_for_payment_result(
97
+ "ses_123",
98
+ timeout=300,
99
+ poll_interval=2,
100
+ )
101
+ ```
102
+
103
+ ## API
104
+
105
+ ### Sessions
106
+
107
+ - `client.sessions.create(...)`
108
+ - `client.sessions.revoke(session_id)`
109
+ - `client.sessions.get_payment_result(session_id)`
110
+ - `client.sessions.wait_for_payment_result(session_id, timeout=300, poll_interval=2)`
111
+ - `client.sessions.report_status(session_id, ...)`
112
+
113
+ The polling helper returns as soon as the result status becomes `awaiting_result`, `completed`, or
114
+ `failed`. It raises `PravaPollingTimeoutError` if the session remains `pending` past the timeout.
115
+
116
+ ### Cards
117
+
118
+ - `client.cards.list(customer_id=..., status="active", include_card_art=False)`
119
+ - `client.cards.delete(customer_id=..., card_id=..., reason="OTHER")`
120
+
121
+ Only non-sensitive card metadata is returned by card-management endpoints.
122
+
123
+ ## Errors
124
+
125
+ All failures derive from `PravaError`. API exceptions expose `code`, `message`, `status_code`,
126
+ `details`, and `response_id` (from the `X-Response-ID` response header):
127
+
128
+ ```python
129
+ from prava_sdk import PravaError
130
+
131
+ try:
132
+ client.sessions.revoke("ses_missing")
133
+ except PravaError as exc:
134
+ print(exc.code, exc.response_id)
135
+ ```
136
+
137
+ The SDK provides dedicated authentication, validation, not-found, invalid-state, rate-limit,
138
+ transport, request-timeout, and polling-timeout exception types. Requests are not retried
139
+ automatically because the API does not currently document idempotency keys.
140
+
141
+ ## Security
142
+
143
+ - Never use `sk_test_*` or `sk_live_*` keys in browsers, mobile apps, logs, or version control.
144
+ - Never collect or send a cardholder's underlying card number through this SDK.
145
+ - Payment-result `token` and `dynamic_cvv` values are Pydantic `SecretStr` fields and are redacted
146
+ from normal model representations. Retrieve them only immediately before checkout.
147
+ - Always call `report_status` with `APPROVED` or `DECLINED` after attempting checkout.
148
+
149
+ See the [API reference](https://docs.prava.space/api-reference/overview),
150
+ [error catalog](https://docs.prava.space/api-reference/errors), and
151
+ [sandbox guide](https://docs.prava.space/api-reference/testing) for the complete server contract.
152
+
153
+ ## Package architecture
154
+
155
+ The SDK is organized as a standalone Python library:
156
+
157
+ ```text
158
+ prava_sdk/
159
+ ├── client.py # Small public sync and async client facades
160
+ ├── resources/ # Session and card endpoint groups
161
+ │ └── _base.py # Shared resource contracts and validation boundary
162
+ ├── models/ # Pydantic requests, responses, and enums
163
+ ├── _config.py # Secret-key and environment resolution
164
+ ├── _transport.py # Shared HTTP, JSON, and response handling
165
+ └── errors.py # Public exception hierarchy
166
+ ```
167
+
168
+ The JavaScript SDK is not a runtime or build dependency. It only handles browser-side card
169
+ collection and is excluded from Python source and wheel distributions.
170
+
171
+ ## Development
172
+
173
+ ```bash
174
+ uv sync --extra dev
175
+ uv run ruff check .
176
+ uv run mypy
177
+ uv run pytest
178
+ uv run mkdocs build --strict
179
+ uv run python -m build
180
+ ```
@@ -0,0 +1,44 @@
1
+ # Architecture
2
+
3
+ The project is a standalone Python library. Browser SDK files are reference material only and are
4
+ not runtime dependencies or package inputs.
5
+
6
+ ```text
7
+ src/prava_sdk/
8
+ ├── client.py
9
+ ├── resources/
10
+ │ ├── _base.py
11
+ │ ├── sessions.py
12
+ │ └── cards.py
13
+ ├── models/
14
+ │ ├── sessions.py
15
+ │ ├── cards.py
16
+ │ ├── enums.py
17
+ │ └── _base.py
18
+ ├── _config.py
19
+ ├── _transport.py
20
+ └── errors.py
21
+ ```
22
+
23
+ ## Responsibilities
24
+
25
+ - `client.py` owns lifecycle and exposes grouped resources.
26
+ - `resources/` maps Python methods to REST paths and builds request models. Its internal base layer
27
+ defines structural transport protocols, so endpoint groups are independent of `httpx` and the
28
+ concrete transport implementation.
29
+ - `models/` validates requests and parses typed responses.
30
+ - `_config.py` resolves secret keys, environments, and base URLs.
31
+ - `_transport.py` owns `httpx` pools, authentication headers, JSON parsing, and transport failures.
32
+ - `errors.py` maps the common Prava error envelope into public exceptions.
33
+
34
+ Sync and async resources share model-building helpers but use distinct transport types. This keeps
35
+ the public APIs symmetrical without hiding blocking I/O inside async methods.
36
+
37
+ Resource methods translate local model errors into `PravaValidationError`; direct use of a public
38
+ Pydantic model still raises Pydantic's `ValidationError`. This keeps the client boundary consistent
39
+ while preserving normal Pydantic behavior for applications that use the schemas independently.
40
+
41
+ ## Compatibility boundary
42
+
43
+ Supported public imports live in `prava_sdk`, `prava_sdk.models`, and the documented client resource
44
+ methods. Underscore-prefixed modules are internal and may change between releases.
@@ -0,0 +1,4 @@
1
+ <svg width="262" height="98" viewBox="0 0 262 98" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M68.452 42.6934L63.6249 39.4767C62.8242 36.9521 61.2403 34.7481 59.1028 33.1841C56.9654 31.6202 54.3854 30.7775 51.7369 30.7783H51.6766C44.8359 30.8116 39.269 36.4865 39.269 43.4311V47.533L21.7372 68.5724L21.7164 68.5974C21.3252 69.086 21.0798 69.6753 21.0086 70.2972C20.9374 70.9192 21.0433 71.5486 21.314 72.1131C21.5847 72.6776 22.0093 73.1541 22.5389 73.488C23.0685 73.8218 23.6816 73.9993 24.3077 74.0001H42.5938C48.3235 73.994 53.8168 71.7152 57.8683 67.6637C61.9198 63.6122 64.1986 58.1189 64.2047 52.3892V48.2914L68.452 45.4612C68.6801 45.3095 68.8671 45.1038 68.9964 44.8623C69.1257 44.6209 69.1934 44.3512 69.1934 44.0773C69.1934 43.8034 69.1257 43.5338 68.9964 43.2923C68.8671 43.0509 68.6801 42.8451 68.452 42.6934ZM45.5341 55.1155L33.0663 70.0769C32.9282 70.2494 32.757 70.3927 32.5628 70.4983C32.3686 70.6039 32.1553 70.6698 31.9354 70.692C31.7155 70.7141 31.4933 70.6922 31.2819 70.6275C31.0706 70.5628 30.8742 70.4566 30.7044 70.3151C30.5346 70.1736 30.3947 69.9997 30.2929 69.8035C30.1911 69.6073 30.1295 69.3927 30.1116 69.1724C30.0937 68.9521 30.12 68.7304 30.1888 68.5203C30.2576 68.3103 30.3677 68.116 30.5125 67.949L42.9803 52.9877C43.1184 52.8151 43.2896 52.6718 43.4838 52.5662C43.678 52.4606 43.8913 52.3948 44.1112 52.3726C44.3311 52.3504 44.5533 52.3723 44.7646 52.437C44.976 52.5017 45.1724 52.6079 45.3422 52.7494C45.512 52.8909 45.6519 53.0648 45.7537 53.2611C45.8555 53.4573 45.9171 53.6718 45.935 53.8921C45.9529 54.1125 45.9266 54.3341 45.8578 54.5442C45.7889 54.7543 45.6789 54.9485 45.5341 55.1155ZM53.3992 44.0773C52.906 44.0773 52.4239 43.9311 52.0139 43.6571C51.6038 43.3831 51.2842 42.9936 51.0955 42.538C50.9067 42.0824 50.8574 41.581 50.9536 41.0973C51.0498 40.6136 51.2873 40.1693 51.636 39.8205C51.9847 39.4718 52.4291 39.2343 52.9128 39.1381C53.3965 39.0419 53.8978 39.0913 54.3535 39.28C54.8091 39.4687 55.1986 39.7883 55.4725 40.1984C55.7465 40.6085 55.8928 41.0906 55.8928 41.5838C55.8928 42.2451 55.6301 42.8793 55.1624 43.347C54.6948 43.8146 54.0606 44.0773 53.3992 44.0773Z" fill="black"/>
3
+ <path d="M110.312 74V26.32H127.144C130.301 26.32 133.075 26.9173 135.464 28.112C137.853 29.3067 139.709 31.0133 141.032 33.232C142.397 35.4507 143.08 38.0533 143.08 41.04C143.08 44.0267 142.397 46.6293 141.032 48.848C139.709 51.024 137.853 52.7307 135.464 53.968C133.117 55.1627 130.344 55.76 127.144 55.76H116.584V74H110.312ZM116.584 50H127.336C129.256 50 130.92 49.6373 132.328 48.912C133.736 48.1867 134.824 47.1413 135.592 45.776C136.36 44.4107 136.744 42.832 136.744 41.04C136.744 39.2053 136.36 37.6267 135.592 36.304C134.824 34.9387 133.736 33.8933 132.328 33.168C130.92 32.4427 129.256 32.08 127.336 32.08H116.584V50ZM147.658 74V39.504H153.482V45.84L152.842 44.944C153.653 42.9813 154.89 41.5307 156.554 40.592C158.218 39.6107 160.245 39.12 162.634 39.12H164.746V44.752H161.738C159.306 44.752 157.343 45.52 155.85 47.056C154.357 48.5493 153.61 50.6827 153.61 53.456V74H147.658ZM176.945 74.768C174.684 74.768 172.678 74.3627 170.929 73.552C169.222 72.6987 167.878 71.5467 166.897 70.096C165.916 68.6027 165.425 66.896 165.425 64.976C165.425 63.1413 165.809 61.4987 166.577 60.048C167.388 58.5547 168.625 57.296 170.289 56.272C171.996 55.248 174.129 54.5227 176.689 54.096L189.489 51.984V56.976L178.033 58.896C175.814 59.28 174.193 59.984 173.169 61.008C172.188 62.032 171.697 63.2907 171.697 64.784C171.697 66.192 172.252 67.3653 173.361 68.304C174.513 69.2427 175.942 69.712 177.649 69.712C179.825 69.712 181.702 69.264 183.281 68.368C184.902 67.4293 186.161 66.1707 187.057 64.592C187.996 63.0133 188.465 61.264 188.465 59.344V50.576C188.465 48.6987 187.761 47.184 186.353 46.032C184.988 44.8373 183.174 44.24 180.913 44.24C178.95 44.24 177.201 44.752 175.665 45.776C174.172 46.7573 173.062 48.08 172.337 49.744L167.153 47.056C167.793 45.4773 168.817 44.0693 170.225 42.832C171.633 41.552 173.276 40.5493 175.153 39.824C177.03 39.0987 178.993 38.736 181.041 38.736C183.686 38.736 186.012 39.248 188.017 40.272C190.022 41.2533 191.58 42.64 192.689 44.432C193.841 46.1813 194.417 48.2293 194.417 50.576V74H188.593V67.472L189.681 67.856C188.956 69.2213 187.974 70.416 186.737 71.44C185.5 72.464 184.049 73.2747 182.385 73.872C180.721 74.4693 178.908 74.768 176.945 74.768ZM209.421 74L195.917 39.504H202.573L213.389 68.688H211.085L221.965 39.504H228.621L215.053 74H209.421ZM239.607 74.768C237.346 74.768 235.341 74.3627 233.591 73.552C231.885 72.6987 230.541 71.5467 229.559 70.096C228.578 68.6027 228.087 66.896 228.087 64.976C228.087 63.1413 228.471 61.4987 229.239 60.048C230.05 58.5547 231.287 57.296 232.951 56.272C234.658 55.248 236.791 54.5227 239.351 54.096L252.151 51.984V56.976L240.695 58.896C238.477 59.28 236.855 59.984 235.831 61.008C234.85 62.032 234.359 63.2907 234.359 64.784C234.359 66.192 234.914 67.3653 236.023 68.304C237.175 69.2427 238.605 69.712 240.311 69.712C242.487 69.712 244.365 69.264 245.943 68.368C247.565 67.4293 248.823 66.1707 249.719 64.592C250.658 63.0133 251.127 61.264 251.127 59.344V50.576C251.127 48.6987 250.423 47.184 249.015 46.032C247.65 44.8373 245.837 44.24 243.575 44.24C241.613 44.24 239.863 44.752 238.327 45.776C236.834 46.7573 235.725 48.08 234.999 49.744L229.815 47.056C230.455 45.4773 231.479 44.0693 232.887 42.832C234.295 41.552 235.938 40.5493 237.815 39.824C239.693 39.0987 241.655 38.736 243.703 38.736C246.349 38.736 248.674 39.248 250.679 40.272C252.685 41.2533 254.242 42.64 255.351 44.432C256.503 46.1813 257.079 48.2293 257.079 50.576V74H251.255V67.472L252.343 67.856C251.618 69.2213 250.637 70.416 249.399 71.44C248.162 72.464 246.711 73.2747 245.047 73.872C243.383 74.4693 241.57 74.768 239.607 74.768Z" fill="black"/>
4
+ </svg>
@@ -0,0 +1,31 @@
1
+ # Examples
2
+
3
+ The repository includes task-focused programs under `examples/`:
4
+
5
+ | File | Demonstrates |
6
+ | --- | --- |
7
+ | `create_hosted_session.py` | Create a hosted cardholder redirect. |
8
+ | `create_embedded_session.py` | Build the payload returned by a backend to its frontend. |
9
+ | `complete_payment.py` | Poll, invoke application checkout logic, and always report status. |
10
+ | `async_payment_flow.py` | Perform the payment orchestration with `AsyncPravaClient`. |
11
+ | `manage_cards.py` | List or delete enrolled cards from a CLI. |
12
+
13
+ Set a sandbox key before running an example:
14
+
15
+ ```bash
16
+ export PRAVA_SECRET_KEY=sk_test_xxx
17
+ python examples/create_hosted_session.py \
18
+ --user-id user_123 \
19
+ --email buyer@example.com \
20
+ --callback-url https://app.example/payments/complete
21
+ ```
22
+
23
+ Display each program's arguments with `--help`:
24
+
25
+ ```bash
26
+ python examples/manage_cards.py --help
27
+ ```
28
+
29
+ The complete-payment examples intentionally require an application-provided merchant checkout
30
+ callback. Prava provides the one-time credential; submitting it to a specific merchant remains the
31
+ application's responsibility.
@@ -0,0 +1,67 @@
1
+ # Getting started
2
+
3
+ ## Install
4
+
5
+ ```bash
6
+ pip install prava-sdk
7
+ ```
8
+
9
+ The package requires Python 3.10 or newer.
10
+
11
+ ## Configure a secret key
12
+
13
+ Pass the key directly when constructing a client:
14
+
15
+ ```python
16
+ from prava_sdk import PravaClient
17
+
18
+ client = PravaClient("sk_test_xxx")
19
+ ```
20
+
21
+ Or set `PRAVA_SECRET_KEY` and omit the argument:
22
+
23
+ ```bash
24
+ export PRAVA_SECRET_KEY=sk_test_xxx
25
+ ```
26
+
27
+ ```python
28
+ from prava_sdk import PravaClient
29
+
30
+ client = PravaClient()
31
+ ```
32
+
33
+ Key prefixes select the API environment automatically:
34
+
35
+ | Prefix | Environment | Base URL |
36
+ | --- | --- | --- |
37
+ | `sk_test_*` | Sandbox | `https://sandbox.api.prava.space` |
38
+ | `sk_live_*` | Production | `https://api.prava.space` |
39
+
40
+ Passing a conflicting `environment` raises `PravaValidationError` before any network request.
41
+
42
+ ## Manage the connection lifecycle
43
+
44
+ Prefer a context manager so the HTTP connection pool is always closed:
45
+
46
+ ```python
47
+ from prava_sdk import PravaClient
48
+
49
+ with PravaClient() as client:
50
+ response = client.cards.list(customer_id="user_123")
51
+ ```
52
+
53
+ Long-running applications can create one client at startup, reuse it for requests, and call
54
+ `close()` during shutdown. Do not create a new client for every operation.
55
+
56
+ For async services, use `AsyncPravaClient` with `async with` or call `aclose()` during shutdown.
57
+
58
+ ## Timeouts and custom transports
59
+
60
+ Set the HTTP timeout at client construction:
61
+
62
+ ```python
63
+ client = PravaClient(timeout=20.0)
64
+ ```
65
+
66
+ The `base_url` and `transport` options exist for local testing and custom `httpx` transports. Normal
67
+ integrations should rely on key-based environment selection.
@@ -0,0 +1,50 @@
1
+ # Async applications
2
+
3
+ `AsyncPravaClient` mirrors the synchronous API. It is appropriate for FastAPI, Starlette, aiohttp,
4
+ and other asyncio-based services.
5
+
6
+ ```python
7
+ from prava_sdk import AsyncPravaClient
8
+
9
+
10
+ async def retrieve_payment(session_id: str) -> None:
11
+ async with AsyncPravaClient() as client:
12
+ result = await client.sessions.wait_for_payment_result(
13
+ session_id,
14
+ timeout=300,
15
+ poll_interval=2,
16
+ )
17
+ print(result.status)
18
+ ```
19
+
20
+ ## Application lifecycle
21
+
22
+ Create one client during application startup and close it during shutdown. For example, the relevant
23
+ FastAPI lifecycle pattern is:
24
+
25
+ ```python
26
+ from contextlib import asynccontextmanager
27
+
28
+ from fastapi import FastAPI
29
+ from prava_sdk import AsyncPravaClient
30
+
31
+
32
+ @asynccontextmanager
33
+ async def lifespan(app: FastAPI):
34
+ app.state.prava = AsyncPravaClient()
35
+ try:
36
+ yield
37
+ finally:
38
+ await app.state.prava.aclose()
39
+
40
+
41
+ app = FastAPI(lifespan=lifespan)
42
+ ```
43
+
44
+ FastAPI is not an SDK dependency; this snippet only demonstrates lifecycle management.
45
+
46
+ ## Cancellation and polling
47
+
48
+ Async polling uses `asyncio.sleep`, so task cancellation is propagated normally. A
49
+ `PravaPollingTimeoutError` is raised when the configured overall timeout expires. The per-request
50
+ HTTP timeout is configured separately on `AsyncPravaClient(timeout=...)`.