apala-api 1.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 (132) hide show
  1. apala_api-1.1.0/.claude/settings.local.json +9 -0
  2. apala_api-1.1.0/.gitignore +10 -0
  3. apala_api-1.1.0/.python-version +1 -0
  4. apala_api-1.1.0/CLAUDE.md +97 -0
  5. apala_api-1.1.0/PKG-INFO +577 -0
  6. apala_api-1.1.0/README.md +526 -0
  7. apala_api-1.1.0/VERIFICATION_RESULTS.md +127 -0
  8. apala_api-1.1.0/apala_client/__init__.py +58 -0
  9. apala_api-1.1.0/apala_client/client.py +290 -0
  10. apala_api-1.1.0/apala_client/metadata.py +136 -0
  11. apala_api-1.1.0/apala_client/models.py +184 -0
  12. apala_api-1.1.0/debug_test.py +101 -0
  13. apala_api-1.1.0/docs/Makefile +32 -0
  14. apala_api-1.1.0/docs/_build/html/.buildinfo +4 -0
  15. apala_api-1.1.0/docs/_build/html/.doctrees/api/client.doctree +0 -0
  16. apala_api-1.1.0/docs/_build/html/.doctrees/api/models.doctree +0 -0
  17. apala_api-1.1.0/docs/_build/html/.doctrees/api/types.doctree +0 -0
  18. apala_api-1.1.0/docs/_build/html/.doctrees/authentication.doctree +0 -0
  19. apala_api-1.1.0/docs/_build/html/.doctrees/environment.pickle +0 -0
  20. apala_api-1.1.0/docs/_build/html/.doctrees/examples.doctree +0 -0
  21. apala_api-1.1.0/docs/_build/html/.doctrees/feedback_tracking.doctree +0 -0
  22. apala_api-1.1.0/docs/_build/html/.doctrees/index.doctree +0 -0
  23. apala_api-1.1.0/docs/_build/html/.doctrees/message_processing.doctree +0 -0
  24. apala_api-1.1.0/docs/_build/html/.doctrees/quickstart.doctree +0 -0
  25. apala_api-1.1.0/docs/_build/html/_modules/apala_client/client.html +478 -0
  26. apala_api-1.1.0/docs/_build/html/_modules/apala_client/models.html +351 -0
  27. apala_api-1.1.0/docs/_build/html/_modules/index.html +112 -0
  28. apala_api-1.1.0/docs/_build/html/_sources/api/client.rst.txt +137 -0
  29. apala_api-1.1.0/docs/_build/html/_sources/api/models.rst.txt +187 -0
  30. apala_api-1.1.0/docs/_build/html/_sources/api/types.rst.txt +275 -0
  31. apala_api-1.1.0/docs/_build/html/_sources/authentication.rst.txt +278 -0
  32. apala_api-1.1.0/docs/_build/html/_sources/examples.rst.txt +553 -0
  33. apala_api-1.1.0/docs/_build/html/_sources/feedback_tracking.rst.txt +391 -0
  34. apala_api-1.1.0/docs/_build/html/_sources/index.rst.txt +122 -0
  35. apala_api-1.1.0/docs/_build/html/_sources/message_processing.rst.txt +384 -0
  36. apala_api-1.1.0/docs/_build/html/_sources/quickstart.rst.txt +289 -0
  37. apala_api-1.1.0/docs/_build/html/_static/_sphinx_javascript_frameworks_compat.js +123 -0
  38. apala_api-1.1.0/docs/_build/html/_static/basic.css +906 -0
  39. apala_api-1.1.0/docs/_build/html/_static/css/badge_only.css +1 -0
  40. apala_api-1.1.0/docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
  41. apala_api-1.1.0/docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
  42. apala_api-1.1.0/docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
  43. apala_api-1.1.0/docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
  44. apala_api-1.1.0/docs/_build/html/_static/css/fonts/fontawesome-webfont.eot +0 -0
  45. apala_api-1.1.0/docs/_build/html/_static/css/fonts/fontawesome-webfont.svg +2671 -0
  46. apala_api-1.1.0/docs/_build/html/_static/css/fonts/fontawesome-webfont.ttf +0 -0
  47. apala_api-1.1.0/docs/_build/html/_static/css/fonts/fontawesome-webfont.woff +0 -0
  48. apala_api-1.1.0/docs/_build/html/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
  49. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-bold-italic.woff +0 -0
  50. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-bold-italic.woff2 +0 -0
  51. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-bold.woff +0 -0
  52. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-bold.woff2 +0 -0
  53. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-normal-italic.woff +0 -0
  54. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-normal-italic.woff2 +0 -0
  55. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-normal.woff +0 -0
  56. apala_api-1.1.0/docs/_build/html/_static/css/fonts/lato-normal.woff2 +0 -0
  57. apala_api-1.1.0/docs/_build/html/_static/css/theme.css +4 -0
  58. apala_api-1.1.0/docs/_build/html/_static/doctools.js +149 -0
  59. apala_api-1.1.0/docs/_build/html/_static/documentation_options.js +13 -0
  60. apala_api-1.1.0/docs/_build/html/_static/file.png +0 -0
  61. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bold.eot +0 -0
  62. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bold.ttf +0 -0
  63. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bold.woff +0 -0
  64. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bold.woff2 +0 -0
  65. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bolditalic.eot +0 -0
  66. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
  67. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff +0 -0
  68. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
  69. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-italic.eot +0 -0
  70. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-italic.ttf +0 -0
  71. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-italic.woff +0 -0
  72. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-italic.woff2 +0 -0
  73. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-regular.eot +0 -0
  74. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-regular.ttf +0 -0
  75. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-regular.woff +0 -0
  76. apala_api-1.1.0/docs/_build/html/_static/fonts/Lato/lato-regular.woff2 +0 -0
  77. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
  78. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
  79. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
  80. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
  81. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
  82. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
  83. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
  84. apala_api-1.1.0/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
  85. apala_api-1.1.0/docs/_build/html/_static/jquery.js +2 -0
  86. apala_api-1.1.0/docs/_build/html/_static/js/badge_only.js +1 -0
  87. apala_api-1.1.0/docs/_build/html/_static/js/theme.js +1 -0
  88. apala_api-1.1.0/docs/_build/html/_static/js/versions.js +228 -0
  89. apala_api-1.1.0/docs/_build/html/_static/language_data.js +192 -0
  90. apala_api-1.1.0/docs/_build/html/_static/minus.png +0 -0
  91. apala_api-1.1.0/docs/_build/html/_static/plus.png +0 -0
  92. apala_api-1.1.0/docs/_build/html/_static/pygments.css +75 -0
  93. apala_api-1.1.0/docs/_build/html/_static/searchtools.js +635 -0
  94. apala_api-1.1.0/docs/_build/html/_static/sphinx_highlight.js +154 -0
  95. apala_api-1.1.0/docs/_build/html/api/client.html +789 -0
  96. apala_api-1.1.0/docs/_build/html/api/models.html +1157 -0
  97. apala_api-1.1.0/docs/_build/html/api/types.html +1206 -0
  98. apala_api-1.1.0/docs/_build/html/authentication.html +394 -0
  99. apala_api-1.1.0/docs/_build/html/examples.html +660 -0
  100. apala_api-1.1.0/docs/_build/html/feedback_tracking.html +521 -0
  101. apala_api-1.1.0/docs/_build/html/genindex.html +465 -0
  102. apala_api-1.1.0/docs/_build/html/index.html +326 -0
  103. apala_api-1.1.0/docs/_build/html/message_processing.html +505 -0
  104. apala_api-1.1.0/docs/_build/html/objects.inv +0 -0
  105. apala_api-1.1.0/docs/_build/html/py-modindex.html +140 -0
  106. apala_api-1.1.0/docs/_build/html/quickstart.html +410 -0
  107. apala_api-1.1.0/docs/_build/html/search.html +130 -0
  108. apala_api-1.1.0/docs/_build/html/searchindex.js +1 -0
  109. apala_api-1.1.0/docs/api/client.rst +137 -0
  110. apala_api-1.1.0/docs/api/models.rst +187 -0
  111. apala_api-1.1.0/docs/api/types.rst +275 -0
  112. apala_api-1.1.0/docs/authentication.rst +278 -0
  113. apala_api-1.1.0/docs/conf.py +111 -0
  114. apala_api-1.1.0/docs/examples.rst +553 -0
  115. apala_api-1.1.0/docs/feedback_tracking.rst +334 -0
  116. apala_api-1.1.0/docs/index.rst +122 -0
  117. apala_api-1.1.0/docs/make.bat +35 -0
  118. apala_api-1.1.0/docs/message_processing.rst +384 -0
  119. apala_api-1.1.0/docs/quickstart.rst +289 -0
  120. apala_api-1.1.0/main.py +9 -0
  121. apala_api-1.1.0/notebooks/apala_demo.py +786 -0
  122. apala_api-1.1.0/notebooks/apala_demo_marimo.py +1139 -0
  123. apala_api-1.1.0/pyproject.toml +97 -0
  124. apala_api-1.1.0/test_core_functionality.py +87 -0
  125. apala_api-1.1.0/test_typed_responses.py +75 -0
  126. apala_api-1.1.0/tests/__init__.py +1 -0
  127. apala_api-1.1.0/tests/conftest.py +156 -0
  128. apala_api-1.1.0/tests/test_client.py +318 -0
  129. apala_api-1.1.0/tests/test_integration.py +234 -0
  130. apala_api-1.1.0/tests/test_models.py +256 -0
  131. apala_api-1.1.0/tox.ini +84 -0
  132. apala_api-1.1.0/uv.lock +3604 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read(//Users/mrkaiser/code/loanai/message_analysis_baml_ex/**)"
5
+ ],
6
+ "deny": [],
7
+ "ask": []
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,97 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is `apala-api`, a Python API project in its early stages. The codebase is minimal and appears to be a starter template for a loan/financial AI API service.
8
+
9
+ ## Development Environment
10
+
11
+ - **Python Version**: 3.12 (specified in `.python-version`)
12
+ - **Package Manager**: Uses `uv` for Python package management
13
+ - **Project Structure**: Simple flat structure with main entry point in `main.py`
14
+
15
+ ## Common Commands
16
+
17
+ ### Environment Setup
18
+ ```bash
19
+ # Install specific Python version if needed
20
+ uv python install 3.12
21
+
22
+ # Create virtual environment (uv handles this automatically)
23
+ uv sync
24
+
25
+ # Add dependencies
26
+ uv add <package-name>
27
+
28
+ # Add development dependencies
29
+ uv add --dev pytest ruff mypy
30
+ ```
31
+
32
+ ### Running the Application
33
+ ```bash
34
+ # Run the main application
35
+ uv run python main.py
36
+
37
+ # Or run directly
38
+ uv run main.py
39
+ ```
40
+
41
+ ### Testing
42
+ ```bash
43
+ # Run tests (once pytest is added)
44
+ uv run pytest
45
+
46
+ # Run tests with coverage
47
+ uv run pytest --cov
48
+
49
+ # Run specific test file
50
+ uv run pytest tests/test_example.py
51
+ ```
52
+
53
+ ### Development Tools
54
+ ```bash
55
+ # Run linting
56
+ uv run ruff check .
57
+
58
+ # Run type checking
59
+ uv run mypy .
60
+
61
+ # Format code
62
+ uv run ruff format .
63
+ ```
64
+
65
+ ### Documentation Commands
66
+ ```bash
67
+ # Build HTML documentation
68
+ uv run sphinx-build -b html docs docs/_build/html
69
+
70
+ # Clean documentation build directory
71
+ uv run python -c "import shutil; shutil.rmtree('docs/_build', ignore_errors=True)"
72
+
73
+ # Live documentation with auto-reload (opens on http://localhost:8001)
74
+ uv run sphinx-autobuild docs docs/_build/html --port 8001
75
+
76
+ # Check for broken links in documentation
77
+ uv run sphinx-build -b linkcheck docs docs/_build/linkcheck
78
+
79
+ # Open documentation in browser (macOS)
80
+ open docs/_build/html/index.html
81
+ ```
82
+
83
+ ## Architecture
84
+
85
+ The current codebase is minimal:
86
+ - `main.py`: Contains a simple entry point with a "Hello World" style function
87
+ - `pyproject.toml`: Basic Python project configuration with no dependencies yet
88
+ - No additional modules, tests, or complex architecture present
89
+
90
+ This appears to be a greenfield project ready for API development, likely intended for loan/financial AI services based on the project name.
91
+
92
+ ## Key Files
93
+
94
+ - `main.py`: Application entry point
95
+ - `pyproject.toml`: Python project configuration and dependencies
96
+ - `.python-version`: Specifies Python 3.12 requirement
97
+ - `.gitignore`: Standard Python gitignore patterns
@@ -0,0 +1,577 @@
1
+ Metadata-Version: 2.4
2
+ Name: apala-api
3
+ Version: 1.1.0
4
+ Summary: Python SDK for Phoenix Message Analysis Services - Loan/Financial AI API Client
5
+ Author: Apala Cap
6
+ Keywords: ai,api,financial,loans,messaging,phoenix
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Office/Business :: Financial
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.9
17
+ Requires-Dist: marimo>=0.16.5
18
+ Requires-Dist: pydantic>=2.12.3
19
+ Requires-Dist: requests>=2.28.0
20
+ Provides-Extra: all
21
+ Requires-Dist: jupyter>=1.0.0; extra == 'all'
22
+ Requires-Dist: marimo>=0.3.0; extra == 'all'
23
+ Requires-Dist: mypy>=1.0.0; extra == 'all'
24
+ Requires-Dist: myst-parser>=3.0.1; extra == 'all'
25
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
26
+ Requires-Dist: pytest-mock>=3.10.0; extra == 'all'
27
+ Requires-Dist: pytest>=7.0.0; extra == 'all'
28
+ Requires-Dist: ruff>=0.1.0; extra == 'all'
29
+ Requires-Dist: sphinx-autodoc-typehints>=2.3.0; extra == 'all'
30
+ Requires-Dist: sphinx-rtd-theme>=3.0.2; extra == 'all'
31
+ Requires-Dist: sphinx>=7.4.7; extra == 'all'
32
+ Requires-Dist: tox>=4.0.0; extra == 'all'
33
+ Requires-Dist: types-requests>=2.28.0; extra == 'all'
34
+ Provides-Extra: dev
35
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
36
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
37
+ Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
38
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
39
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
40
+ Requires-Dist: tox>=4.0.0; extra == 'dev'
41
+ Requires-Dist: types-requests>=2.28.0; extra == 'dev'
42
+ Provides-Extra: docs
43
+ Requires-Dist: myst-parser>=3.0.1; extra == 'docs'
44
+ Requires-Dist: sphinx-autodoc-typehints>=2.3.0; extra == 'docs'
45
+ Requires-Dist: sphinx-rtd-theme>=3.0.2; extra == 'docs'
46
+ Requires-Dist: sphinx>=7.4.7; extra == 'docs'
47
+ Provides-Extra: notebook
48
+ Requires-Dist: jupyter>=1.0.0; extra == 'notebook'
49
+ Requires-Dist: marimo>=0.3.0; extra == 'notebook'
50
+ Description-Content-Type: text/markdown
51
+
52
+ # Apala API - Python SDK
53
+
54
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
55
+ [![Type Hints](https://img.shields.io/badge/type--hints-yes-brightgreen)](https://docs.python.org/3/library/typing.html)
56
+
57
+
58
+ ## 🚀 Quick Start
59
+
60
+ ### Installation
61
+
62
+ ```bash
63
+ # Install from source (package not yet published to PyPI)
64
+ git clone <repository-url>
65
+ cd apala_api
66
+
67
+ # Basic installation
68
+ uv sync
69
+
70
+ # Or install with development tools
71
+ uv sync --group dev
72
+
73
+ # Or install with notebook support
74
+ uv sync --group notebook
75
+ ```
76
+
77
+ ### Basic Usage
78
+
79
+ ```python
80
+ from apala_client import ApalaClient, Message
81
+
82
+ # Initialize client
83
+ client = ApalaClient(
84
+ api_key="your-api-key",
85
+ base_url="https://your-server.com"
86
+ )
87
+
88
+ # Authenticate (automatic JWT token management)
89
+ client.authenticate()
90
+
91
+ # Create customer message history
92
+ messages = [
93
+ Message(content="Hi, I need help with my loan application.", channel="EMAIL", reply_or_not=False),
94
+ Message(content="What are the current interest rates?", channel="SMS", reply_or_not=True),
95
+ Message(content="When will I hear back about approval?", channel="EMAIL", reply_or_not=True)
96
+ ]
97
+
98
+ # Create your candidate response
99
+ candidate = Message(
100
+ content="Thank you for your inquiry! Our current rates start at 3.5% APR for qualified borrowers. We'll review your application and respond within 2 business days.",
101
+ channel="EMAIL",
102
+ reply_or_not=True
103
+ )
104
+
105
+ # Optimize message through the AI system
106
+ optimization = client.optimize_message(
107
+ message_history=messages,
108
+ candidate_message=candidate,
109
+ customer_id="550e8400-e29b-41d4-a716-446655440000",
110
+ zip_code="90210",
111
+ company_guid="550e8400-e29b-41d4-a716-446655440001"
112
+ )
113
+
114
+ print(f"Original: {optimization.original_message}")
115
+ print(f"Optimized: {optimization.optimized_message}")
116
+ print(f"Message ID: {optimization.message_id}")
117
+
118
+ # Submit feedback after customer interaction
119
+ feedback_result = client.submit_single_feedback(
120
+ message_id=optimization.message_id,
121
+ customer_responded=True,
122
+ score="good", # "good", "bad", or "neutral"
123
+ actual_sent_message=optimization.optimized_message # Optional: what you actually sent
124
+ )
125
+
126
+ print(f"Feedback ID: {feedback_result.id}")
127
+ print(f"Submitted at: {feedback_result.inserted_at}")
128
+ ```
129
+
130
+ ## 🎯 Core Features
131
+
132
+ ### ✅ **Type-Safe API**
133
+ - Full **TypedDict** responses with IDE autocomplete
134
+ - **mypy** integration catches errors at development time
135
+ - **No runtime surprises** - all response fields are typed
136
+
137
+ ### ✅ **Complete Functionality**
138
+ - **Message Optimization**: Enhance messages for maximum engagement (primary endpoint)
139
+ - **Message Processing**: Analyze customer conversations and candidate responses
140
+ - **Feedback Tracking**: Monitor message performance with single or bulk submission
141
+ - **Authentication**: Automatic JWT token management with refresh
142
+
143
+ ### ✅ **Production Ready**
144
+ - **Multi-Python Support**: Python 3.9, 3.10, 3.11, 3.12
145
+ - **Comprehensive Testing**: Unit tests, integration tests, type checking
146
+ - **Error Handling**: Uses standard `requests` exceptions (no custom exceptions)
147
+ - **Validation**: Client-side validation of UUIDs, zip codes, channels
148
+
149
+ ### ✅ **Developer Experience**
150
+ - **Interactive Demo**: Marimo notebook with complete workflow
151
+ - **Documentation**: Full Sphinx docs with examples
152
+ - **Code Quality**: Ruff formatting, mypy type checking, tox multi-version testing
153
+
154
+ ## 📖 Documentation
155
+
156
+ ### Authentication
157
+
158
+ The SDK uses a secure two-tier authentication system:
159
+
160
+ 1. **API Key**: Your long-lived company credentials
161
+ 2. **JWT Tokens**: Short-lived session tokens for API calls (auto-managed)
162
+
163
+ ```python
164
+ # Authentication is automatic - just provide your API key
165
+ client = ApalaClient(api_key="your-api-key")
166
+ auth_response = client.authenticate()
167
+
168
+ # JWT tokens are automatically refreshed when needed
169
+ # No manual token management required!
170
+ ```
171
+
172
+ ### Message Processing Workflow
173
+
174
+ ```python
175
+ # 1. Create message objects with validation
176
+ customer_messages = [
177
+ Message(
178
+ content="I'm interested in a home loan",
179
+ channel="EMAIL",
180
+ reply_or_not=False
181
+ ),
182
+ Message(
183
+ content="What documents do I need?",
184
+ channel="SMS",
185
+ reply_or_not=True
186
+ )
187
+ ]
188
+
189
+ # 2. Define your candidate response
190
+ candidate_response = Message(
191
+ content="Great! For a home loan, you'll need: income verification, credit report, and bank statements. We offer competitive rates starting at 3.2% APR.",
192
+ channel="EMAIL",
193
+ reply_or_not=True
194
+ )
195
+
196
+ # 3. Optimize through AI system
197
+ result = client.optimize_message(
198
+ message_history=customer_messages,
199
+ candidate_message=candidate_response,
200
+ customer_id="customer-uuid-here",
201
+ zip_code="12345",
202
+ company_guid="company-uuid-here"
203
+ )
204
+
205
+ # 4. Get typed response with IDE completion
206
+ message_id = result.message_id # Type: str
207
+ optimized_message = result.optimized_message # Type: str
208
+ recommended_channel = result.recommended_channel # Type: str
209
+ ```
210
+
211
+ ### Message Optimization
212
+
213
+ Enhance your messages for better customer engagement:
214
+
215
+ ```python
216
+ # Optimize your message for maximum engagement
217
+ optimization = client.optimize_message(
218
+ message_history=customer_messages,
219
+ candidate_message=candidate_response,
220
+ customer_id="customer-uuid",
221
+ zip_code="12345",
222
+ company_guid="company-uuid"
223
+ )
224
+
225
+ print(f"Original: {optimization.original_message}")
226
+ print(f"Optimized: {optimization.optimized_message}")
227
+ print(f"Recommended channel: {optimization.recommended_channel}")
228
+ print(f"Message ID: {optimization.message_id}")
229
+ ```
230
+
231
+ ### Feedback Tracking
232
+
233
+ Monitor message performance and learn from customer interactions:
234
+
235
+ ```python
236
+ # Track how customers respond to your messages
237
+ result = client.submit_single_feedback(
238
+ message_id="message-id-from-optimization",
239
+ customer_responded=True,
240
+ score="good", # "good", "bad", or "neutral"
241
+ actual_sent_message="The actual message you sent" # Optional
242
+ )
243
+
244
+ print(f"Feedback recorded with ID: {result.id}")
245
+ print(f"Submitted at: {result.inserted_at}")
246
+
247
+ # Or submit multiple feedback items at once
248
+ feedback_list = [
249
+ {
250
+ "message_id": "msg-uuid-1",
251
+ "customer_responded": True,
252
+ "score": "good",
253
+ "actual_sent_message": "Message 1 content"
254
+ },
255
+ {
256
+ "message_id": "msg-uuid-2",
257
+ "customer_responded": False,
258
+ "score": "neutral"
259
+ }
260
+ ]
261
+ results = client.submit_feedback_bulk(feedback_list)
262
+ print(f"Submitted {results.count} feedback items")
263
+ ```
264
+
265
+ ## 🔧 Configuration
266
+
267
+ ### Environment Variables
268
+
269
+ Set these for production deployment:
270
+
271
+ ```bash
272
+ # Required
273
+ export APALA_API_KEY="your-production-api-key"
274
+ export APALA_BASE_URL="https://your-phoenix-server.com"
275
+ export APALA_COMPANY_GUID="your-company-uuid"
276
+
277
+ # Optional
278
+ export APALA_CUSTOMER_ID="default-customer-uuid" # For testing
279
+ ```
280
+
281
+ ### Client Configuration
282
+
283
+ ```python
284
+ # Basic configuration
285
+ client = ApalaClient(
286
+ api_key="your-key",
287
+ base_url="https://api.yourcompany.com"
288
+ )
289
+
290
+ # Advanced usage with custom session
291
+ import requests
292
+ session = requests.Session()
293
+ session.timeout = 30 # Custom timeout
294
+ client = ApalaClient(api_key="your-key")
295
+ client._session = session
296
+ ```
297
+
298
+ ## 🧪 Testing & Development
299
+
300
+ ### Setup
301
+
302
+ ```bash
303
+ # Clone and install in development mode with uv
304
+ git clone <repository-url>
305
+ cd apala_api
306
+ uv sync --group dev
307
+ ```
308
+
309
+ ### Running Tests
310
+
311
+ ```bash
312
+ # Run unit tests
313
+ uv run pytest tests/test_models.py tests/test_client.py -v
314
+
315
+ # Run with coverage
316
+ uv run pytest --cov=apala_client --cov-report=html
317
+
318
+ # Run integration tests (requires running server)
319
+ # In Fish shell:
320
+ env RUN_INTEGRATION_TESTS=1 APALA_API_KEY=test-key APALA_COMPANY_GUID=test-company-uuid uv run pytest tests/test_integration.py
321
+
322
+ # In Bash/Zsh:
323
+ export RUN_INTEGRATION_TESTS=1 APALA_API_KEY=test-key APALA_COMPANY_GUID=test-company-uuid
324
+ uv run pytest tests/test_integration.py
325
+ ```
326
+
327
+ ### Code Quality
328
+
329
+ ```bash
330
+ # Static type checking
331
+ uv run mypy .
332
+
333
+ # Linting
334
+ uv run ruff check .
335
+
336
+ # Code formatting
337
+ uv run ruff format .
338
+ ```
339
+
340
+ ### Documentation
341
+
342
+ ```bash
343
+ # Build HTML documentation
344
+ uv run sphinx-build -b html docs docs/_build/html
345
+
346
+ # Build with live reload (auto-refreshes on changes)
347
+ uv run sphinx-autobuild docs docs/_build/html --port 8001
348
+
349
+ # Clean build directory
350
+ uv run python -c "import shutil; shutil.rmtree('docs/_build', ignore_errors=True)"
351
+
352
+ # Check for broken links
353
+ uv run sphinx-build -b linkcheck docs docs/_build/linkcheck
354
+ ```
355
+
356
+ ### Multi-Python Testing
357
+
358
+ ```bash
359
+ # Test across Python versions
360
+ uv run tox
361
+
362
+ # Test specific version
363
+ uv run tox -e py311
364
+ ```
365
+
366
+ ## 📊 Interactive Demo
367
+
368
+ Try the complete workflow in an interactive notebook:
369
+
370
+ ```bash
371
+ # Install notebook dependencies
372
+ uv sync --group notebook
373
+
374
+ # Run the interactive demo
375
+ cd notebooks
376
+ marimo run apala_demo_marimo.py
377
+ ```
378
+
379
+ The demo covers:
380
+ - 🔐 Authentication setup
381
+ - 📝 Creating message history
382
+ - 🎯 Message optimization (with optional metadata)
383
+ - 📊 Feedback submission
384
+ - 🔄 Complete end-to-end workflow example
385
+
386
+ ## 🛡️ Error Handling
387
+
388
+ The SDK uses standard Python exceptions - no custom error types to learn:
389
+
390
+ ```python
391
+ import requests
392
+ from apala_client import ApalaClient
393
+
394
+ client = ApalaClient(api_key="your-key")
395
+
396
+ try:
397
+ # All SDK methods may raise requests exceptions
398
+ response = client.optimize_message(...)
399
+
400
+ except requests.HTTPError as e:
401
+ # HTTP errors (4xx, 5xx responses)
402
+ print(f"HTTP {e.response.status_code}: {e}")
403
+
404
+ except requests.ConnectionError as e:
405
+ # Network connectivity issues
406
+ print(f"Connection failed: {e}")
407
+
408
+ except requests.Timeout as e:
409
+ # Request timeout
410
+ print(f"Request timed out: {e}")
411
+
412
+ except requests.RequestException as e:
413
+ # Any other requests-related error
414
+ print(f"Request error: {e}")
415
+
416
+ except ValueError as e:
417
+ # Data validation errors (invalid UUIDs, etc.)
418
+ print(f"Invalid data: {e}")
419
+ ```
420
+
421
+ ## 🔍 API Reference
422
+
423
+ ### ApalaClient
424
+
425
+ Main client class for all API interactions.
426
+
427
+ #### Constructor
428
+ ```python
429
+ ApalaClient(api_key: str, base_url: str = "http://localhost:4000")
430
+ ```
431
+
432
+ #### Methods
433
+
434
+ | Method | Return Type | Description |
435
+ |--------|-------------|-------------|
436
+ | `authenticate()` | `AuthResponse` | Exchange API key for JWT tokens |
437
+ | `refresh_access_token()` | `RefreshResponse` | Refresh access token |
438
+ | `message_process(...)` | `MessageProcessingResponse` | Process customer messages |
439
+ | `optimize_message(...)` | `MessageOptimizationResponse` | Optimize message content |
440
+ | `submit_single_feedback(...)` | `FeedbackResponse` | Submit single feedback |
441
+ | `submit_feedback_bulk(...)` | `BulkFeedbackResponse` | Submit multiple feedback items |
442
+ | `message_feedback(...)` | `BulkFeedbackResponse` | Alias for submit_feedback_bulk |
443
+ | `close()` | `None` | Close HTTP session |
444
+
445
+ ### Data Models
446
+
447
+ #### Message
448
+ Customer or candidate message with validation.
449
+
450
+ ```python
451
+ @dataclass
452
+ class Message:
453
+ content: str # Message text
454
+ channel: str # "SMS", "EMAIL", "OTHER"
455
+ message_id: Optional[str] = None # Auto-generated if None
456
+ send_timestamp: Optional[str] = None # Auto-generated if None
457
+ reply_or_not: bool = False # Whether this is a reply
458
+ ```
459
+
460
+ #### Feedback Submission
461
+ Submit feedback using the client methods directly (no model class needed):
462
+
463
+ ```python
464
+ # Single feedback submission
465
+ client.submit_single_feedback(
466
+ message_id: str, # ID from optimization response
467
+ customer_responded: bool, # Did customer respond?
468
+ score: str, # Quality rating: "good", "bad", or "neutral"
469
+ actual_sent_message: Optional[str] = None # What you actually sent
470
+ )
471
+
472
+ # Bulk feedback submission
473
+ client.submit_feedback_bulk([
474
+ {
475
+ "message_id": str,
476
+ "customer_responded": bool,
477
+ "score": str, # "good", "bad", or "neutral"
478
+ "actual_sent_message": str # Optional
479
+ },
480
+ # ... more feedback items
481
+ ])
482
+ ```
483
+
484
+ ### Response Types
485
+
486
+ All API responses are fully typed with Pydantic models:
487
+
488
+ #### AuthResponse
489
+ ```python
490
+ class AuthResponse(BaseModel):
491
+ access_token: str
492
+ refresh_token: str
493
+ token_type: str
494
+ expires_in: int
495
+ company_id: str
496
+ company_name: str
497
+ ```
498
+
499
+ #### MessageOptimizationResponse
500
+ ```python
501
+ class MessageOptimizationResponse(BaseModel):
502
+ message_id: str
503
+ optimized_message: str
504
+ recommended_channel: str
505
+ original_message: str
506
+ ```
507
+
508
+ #### FeedbackResponse
509
+ ```python
510
+ class FeedbackResponse(BaseModel):
511
+ id: str
512
+ message_id: str
513
+ customer_responded: bool
514
+ score: Literal["good", "bad", "neutral"]
515
+ actual_sent_message: Optional[str]
516
+ inserted_at: str
517
+ ```
518
+
519
+ #### BulkFeedbackResponse
520
+ ```python
521
+ class BulkFeedbackResponse(BaseModel):
522
+ success: bool
523
+ count: int
524
+ feedback: List[FeedbackItemResponse]
525
+ ```
526
+
527
+ *See full API documentation for complete type definitions.*
528
+
529
+ ## 🤝 Contributing
530
+
531
+ We welcome contributions! Please see our contributing guidelines:
532
+
533
+ 1. **Fork** the repository
534
+ 2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
535
+ 3. **Add tests** for new functionality
536
+ 4. **Run the test suite** (`pytest` and `mypy apala_client`)
537
+ 5. **Commit** your changes (`git commit -m 'Add amazing feature'`)
538
+ 6. **Push** to your branch (`git push origin feature/amazing-feature`)
539
+ 7. **Create** a Pull Request
540
+
541
+ ### Development Setup
542
+
543
+ ```bash
544
+ git clone <your-fork>
545
+ cd apala_api
546
+ uv sync --group dev
547
+
548
+ # Run all checks before submitting
549
+ uv run pytest # Unit tests
550
+ uv run mypy apala_client # Type checking
551
+ uv run ruff check apala_client # Linting
552
+ uv run ruff format apala_client # Formatting
553
+ uv run tox # Multi-Python testing
554
+ ```
555
+
556
+ ## 📄 License
557
+
558
+ Copyright (c) 2025 Apala Cap. All rights reserved.
559
+
560
+ This software is proprietary and confidential. Unauthorized copying, distribution, or use of this software, via any medium, is strictly prohibited.
561
+
562
+ ## 🔗 Links
563
+
564
+ - **Documentation**: [Full API Documentation](docs/)
565
+ - **Source Code**: [GitHub Repository](#)
566
+ - **Issue Tracker**: [GitHub Issues](#)
567
+ - **PyPI Package**: [apala-api](#)
568
+
569
+ ## 💬 Support
570
+
571
+ - **GitHub Issues**: For bugs and feature requests
572
+ - **Documentation**: Complete API reference and guides
573
+ - **Type Safety**: Full mypy support for development-time error catching
574
+
575
+ ---
576
+
577
+ *Apala API - Proprietary Software by Apala Cap*