Tax Practice AI - API Specification¶
Version: 1.1
Last Updated: 2025-12-28
Status: Draft
Base URL: https://api.taxpractice.example.com/v1
Table of Contents¶
- Overview
- Authentication
- Common Patterns
- Clients API
- Returns API
- Documents API
- Questions API
- Messages API
- Invoices API
- Engagements API
- E-Filing API
- Identity Verification API
- Webhooks API
- Admin API
Related Documentation¶
| Document | Purpose |
|---|---|
| DATA_MODEL.md | Entity definitions (35+ entities) |
| PROCESS_FLOWS.md | State machines and workflows |
| SECURITY_DESIGN.md | Authentication and authorization details |
| INTEGRATION_CONTRACTS.md | External system specifications |
1. Overview¶
1.1 Design Principles¶
| Principle | Implementation |
|---|---|
| RESTful | Resource-based URLs, standard HTTP methods |
| JSON | All request/response bodies are JSON |
| Versioned | URL versioning (/v1/, /v2/) |
| Consistent | Standard response envelopes, error formats |
| Secure | JWT authentication, role-based access |
| Auditable | Correlation IDs for all requests |
1.2 URL Structure¶
Examples:
- GET /v1/clients - List clients
- GET /v1/clients/{id} - Get client
- GET /v1/clients/{id}/returns - List client's returns
- POST /v1/returns/{id}/workflow/transition - Transition workflow state
1.3 HTTP Methods¶
| Method | Usage | Idempotent |
|---|---|---|
GET |
Retrieve resources | Yes |
POST |
Create resources, actions | No |
PUT |
Replace resource | Yes |
PATCH |
Partial update | No |
DELETE |
Soft delete resource | Yes |
1.4 Content Types¶
| Direction | Content-Type |
|---|---|
| Request | application/json |
| Response | application/json |
| File upload | multipart/form-data |
| File download | application/pdf, image/*, etc. |
2. Authentication¶
2.1 JWT Authentication¶
Header Format:
Token Structure:
{
"sub": "user-uuid",
"role": "preparer",
"email": "user@example.com",
"client_ids": ["uuid-1"],
"exp": 1703376000,
"iat": 1703374200,
"jti": "unique-token-id"
}
2.2 Authentication Endpoints¶
POST /v1/auth/login¶
Staff login with credentials.
Request:
Response (200 - MFA Required):
{
"status": "mfa_required",
"mfa_token": "temporary-mfa-token",
"mfa_methods": ["totp", "webauthn"]
}
POST /v1/auth/mfa/verify¶
Complete MFA verification.
Request:
Response (200):
{
"access_token": "eyJhbGciOiJSUzI1NiI...",
"refresh_token": "refresh-token-value",
"expires_in": 1800,
"token_type": "Bearer"
}
POST /v1/auth/refresh¶
Refresh access token.
Request:
Response (200):
POST /v1/auth/logout¶
Invalidate current session.
Response (204): No content
2.3 Client Portal Authentication¶
POST /v1/portal/auth/magic-link¶
Request magic link for client login.
Request:
Response (200):
POST /v1/portal/auth/verify-link¶
Verify magic link token.
Request:
Response (200):
3. Common Patterns¶
3.1 Request Headers¶
| Header | Required | Description |
|---|---|---|
Authorization |
Yes (except auth endpoints) | Bearer JWT token |
Content-Type |
Yes (POST/PUT/PATCH) | application/json |
X-Correlation-ID |
No | Client-generated trace ID |
X-Idempotency-Key |
No (recommended for POST) | Prevents duplicate operations |
3.2 Response Envelope¶
Success Response:
{
"data": { ... },
"meta": {
"request_id": "req-uuid",
"correlation_id": "client-trace-id",
"timestamp": "2024-12-23T10:30:00Z"
}
}
List Response:
{
"data": [ ... ],
"meta": {
"request_id": "req-uuid",
"correlation_id": "client-trace-id",
"timestamp": "2024-12-23T10:30:00Z"
},
"pagination": {
"cursor": "next-cursor-value",
"has_more": true,
"total_count": 150
}
}
3.3 Error Response (RFC 7807)¶
{
"type": "https://api.taxpractice.example.com/errors/validation",
"title": "Validation Error",
"status": 400,
"detail": "One or more fields failed validation",
"instance": "/v1/clients",
"errors": [
{
"field": "email",
"code": "invalid_format",
"message": "Email must be a valid email address"
}
],
"meta": {
"request_id": "req-uuid",
"correlation_id": "client-trace-id",
"timestamp": "2024-12-23T10:30:00Z"
}
}
3.4 HTTP Status Codes¶
| Code | Meaning | Usage |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST creating resource |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Validation error |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | State conflict (e.g., duplicate) |
| 422 | Unprocessable Entity | Business rule violation |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unexpected server error |
3.5 Pagination (Cursor-Based)¶
Request:
Parameters:
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
limit |
integer | 25 | 100 | Items per page |
cursor |
string | null | - | Opaque cursor from previous response |
Response:
{
"data": [...],
"pagination": {
"cursor": "eyJpZCI6Inh5ejc4OSJ9",
"has_more": true,
"total_count": 150
}
}
3.6 Filtering and Sorting¶
Query Parameters:
| Parameter | Description | Example |
|---|---|---|
{field} |
Filter by field value | status=in_prep |
{field}__gte |
Greater than or equal | created_at__gte=2024-01-01 |
{field}__lte |
Less than or equal | amount__lte=10000 |
{field}__in |
In list | status__in=in_prep,ready_for_review |
sort |
Sort field (prefix - for desc) |
sort=-created_at |
fields |
Sparse fieldset | fields=id,status,client_id |
3.7 Rate Limiting¶
Headers:
Limits:
| Endpoint Type | Limit | Window |
|---|---|---|
| Standard | 1000 requests | 5 minutes |
| Auth | 10 requests | 1 minute |
| File upload | 100 requests | 5 minutes |
| Webhooks | 500 requests | 1 minute |
4. Clients API¶
4.1 List Clients¶
GET /v1/clients
Permissions: Admin, EA/CPA, Reviewer (all), Preparer (assigned only)
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status (active, inactive, closed) |
client_type |
string | Filter by type (individual, business, trust, nonprofit) |
assigned_preparer_id |
uuid | Filter by assigned preparer |
search |
string | Search name, email, account_number |
Response (200):
{
"data": [
{
"id": "uuid",
"account_number": "C-2024-00001",
"client_type": "individual",
"name": "John Smith",
"email": "john.smith@example.com",
"phone": "+1-555-123-4567",
"status": "active",
"assigned_preparer_id": "preparer-uuid",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-12-20T14:22:00Z"
}
],
"pagination": {
"cursor": "eyJpZCI6ImFiYzEyMyJ9",
"has_more": true,
"total_count": 150
}
}
4.2 Get Client¶
GET /v1/clients/{id}
Permissions: Admin, EA/CPA, Reviewer, Preparer (if assigned), Client (own only)
Response (200):
{
"data": {
"id": "uuid",
"account_number": "C-2024-00001",
"client_type": "individual",
"name": "John Smith",
"email": "john.smith@example.com",
"phone": "+1-555-123-4567",
"address": {
"street1": "123 Main St",
"street2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"zip": "94102"
},
"ssn_last4": "1234",
"date_of_birth": "1980-05-15",
"status": "active",
"identity_verification_status": "verified",
"assigned_preparer_id": "preparer-uuid",
"contacts": [
{
"id": "contact-uuid",
"name": "Jane Smith",
"relationship": "spouse",
"email": "jane.smith@example.com",
"phone": "+1-555-234-5678",
"is_primary": false
}
],
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-12-20T14:22:00Z"
}
}
4.3 Create Client¶
POST /v1/clients
Permissions: Admin, EA/CPA, Reviewer, Preparer
Request:
{
"client_type": "individual",
"name": "John Smith",
"email": "john.smith@example.com",
"phone": "+1-555-123-4567",
"address": {
"street1": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip": "94102"
},
"ssn": "123-45-6789",
"date_of_birth": "1980-05-15"
}
Response (201):
4.4 Update Client¶
PATCH /v1/clients/{id}
Permissions: Admin, EA/CPA, Reviewer, Preparer (if assigned)
Request:
Response (200): Updated client object
4.5 Delete Client (Soft)¶
DELETE /v1/clients/{id}
Permissions: Admin only
Response (204): No content
4.6 Client Contacts¶
List Contacts¶
GET /v1/clients/{id}/contacts
Add Contact¶
POST /v1/clients/{id}/contacts
Request:
{
"name": "Jane Smith",
"relationship": "spouse",
"email": "jane.smith@example.com",
"phone": "+1-555-234-5678",
"is_primary": false
}
Update Contact¶
PATCH /v1/clients/{client_id}/contacts/{contact_id}
Delete Contact¶
DELETE /v1/clients/{client_id}/contacts/{contact_id}
5. Returns API¶
5.1 List Returns¶
GET /v1/returns
Permissions: Admin, EA/CPA, Reviewer (all), Preparer (assigned only), Client (own only)
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
client_id |
uuid | Filter by client |
tax_year |
integer | Filter by tax year |
status |
string | Filter by workflow status |
return_type |
string | Filter by type (1040, 1120S, etc.) |
assigned_preparer_id |
uuid | Filter by preparer |
Response (200):
{
"data": [
{
"id": "return-uuid",
"client_id": "client-uuid",
"client_name": "John Smith",
"tax_year": 2024,
"return_type": "1040",
"filing_status": "married_joint",
"status": "in_prep",
"progress_percentage": 50,
"assigned_preparer_id": "preparer-uuid",
"assigned_reviewer_id": null,
"extension_filed": false,
"created_at": "2024-01-20T09:00:00Z",
"updated_at": "2024-12-22T16:45:00Z"
}
]
}
5.2 Get Return¶
GET /v1/returns/{id}
Response (200):
{
"data": {
"id": "return-uuid",
"client_id": "client-uuid",
"tax_year": 2024,
"return_type": "1040",
"filing_status": "married_joint",
"status": "in_prep",
"progress_percentage": 50,
"assigned_preparer_id": "preparer-uuid",
"assigned_reviewer_id": null,
"extension_filed": false,
"extension_date": null,
"due_date": "2025-04-15",
"priority": "normal",
"estimated_refund": 2500.00,
"estimated_tax_due": null,
"federal_status": "in_progress",
"state_filings": [
{
"state": "CA",
"status": "in_progress"
}
],
"workflow_history": [
{
"from_status": "ready_for_prep",
"to_status": "in_prep",
"transitioned_at": "2024-12-22T10:00:00Z",
"transitioned_by": "preparer-uuid",
"notes": "Starting preparation"
}
],
"created_at": "2024-01-20T09:00:00Z",
"updated_at": "2024-12-22T16:45:00Z"
}
}
5.3 Create Return¶
POST /v1/returns
Permissions: Admin, EA/CPA, Reviewer, Preparer
Request:
{
"client_id": "client-uuid",
"tax_year": 2024,
"return_type": "1040",
"filing_status": "married_joint",
"assigned_preparer_id": "preparer-uuid"
}
Response (201): Created return object
5.4 Update Return¶
PATCH /v1/returns/{id}
Permissions: Admin, EA/CPA, Reviewer, Preparer (if assigned)
Request:
Response (200): Updated return object
5.5 Delete Return (Soft)¶
DELETE /v1/returns/{id}
Permissions: Admin, EA/CPA
Notes: Soft delete only - sets deleted_at timestamp. Returns with filed status cannot be deleted.
Response (204): No content
5.6 Workflow Transition¶
POST /v1/returns/{id}/workflow/transition
Permissions: Varies by transition (see PROCESS_FLOWS.md)
Request:
Valid Actions:
| Action | From Status | To Status | Required Role |
|---|---|---|---|
start_prep |
ready_for_prep | ai_analysis | Preparer |
complete_ai_analysis |
ai_analysis | in_prep | System |
request_client_info |
in_prep | pending_client_response | Preparer |
client_responded |
pending_client_response | in_prep | System |
submit_for_review |
in_prep | ready_for_review | Preparer |
start_review |
ready_for_review | in_review | Reviewer |
request_revisions |
in_review | revisions_needed | Reviewer |
approve |
in_review | approved | Reviewer/EA |
send_for_signature |
approved | pending_signature | System |
signature_received |
pending_signature | ready_to_file | System |
transmit |
ready_to_file | filed | System |
mark_accepted |
filed | accepted | System |
mark_rejected |
filed | rejected | System |
restart_after_rejection |
rejected | in_prep | Preparer/EA |
complete |
accepted | complete | System |
Response (200):
{
"data": {
"id": "return-uuid",
"status": "ready_for_review",
"previous_status": "in_prep",
"transitioned_at": "2024-12-23T11:00:00Z"
}
}
5.7 Get Workflow State¶
GET /v1/returns/{id}/workflow/state
Returns the current workflow state with full history.
Response (200):
{
"data": {
"current_status": "in_review",
"entered_at": "2024-12-23T10:00:00Z",
"days_in_status": 1,
"assigned_to": "reviewer-uuid",
"history": [
{
"from_status": "in_prep",
"to_status": "ready_for_review",
"transitioned_at": "2024-12-22T16:00:00Z",
"transitioned_by": "preparer-uuid",
"notes": "Ready for review"
},
{
"from_status": "ready_for_review",
"to_status": "in_review",
"transitioned_at": "2024-12-23T10:00:00Z",
"transitioned_by": "reviewer-uuid",
"notes": "Starting review"
}
]
}
}
5.8 AI Analysis¶
POST /v1/returns/{id}/ai/analyze
Permissions: Admin, EA/CPA, Reviewer, Preparer
Triggers AI analysis of the return.
Request:
Response (202):
{
"data": {
"analysis_id": "analysis-uuid",
"status": "processing",
"estimated_completion": "2024-12-23T11:05:00Z"
}
}
5.9 Get AI Analysis¶
GET /v1/returns/{id}/ai/analysis/{analysis_id}
Response (200):
{
"data": {
"id": "analysis-uuid",
"status": "completed",
"completed_at": "2024-12-23T11:03:00Z",
"findings": [
{
"type": "missing_document",
"severity": "high",
"description": "1099-B from brokerage not found",
"recommendation": "Request brokerage statement from client"
},
{
"type": "prior_year_variance",
"severity": "medium",
"description": "Interest income increased 150% from prior year",
"recommendation": "Verify with client - may indicate new accounts"
}
],
"suggested_questions": [
{
"id": "q-uuid-1",
"question": "Did you open any new investment accounts in 2024?",
"context": "Interest income significantly higher than prior year"
}
]
}
}
6. Documents API¶
6.1 List Documents¶
GET /v1/documents
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
client_id |
uuid | Filter by client |
return_id |
uuid | Filter by return |
tax_year |
integer | Filter by tax year |
document_type |
string | Filter by type (w2, 1099_div, etc.) |
status |
string | Filter by status |
Response (200):
{
"data": [
{
"id": "doc-uuid",
"client_id": "client-uuid",
"return_id": "return-uuid",
"tax_year": 2024,
"document_type": "W-2",
"document_subtype": null,
"filename": "W2_Employer_2024.pdf",
"file_size": 125000,
"mime_type": "application/pdf",
"status": "extracted",
"extraction_confidence": 0.95,
"source": "client_upload",
"uploaded_at": "2024-12-20T10:00:00Z",
"processed_at": "2024-12-20T10:02:00Z"
}
]
}
6.2 Get Document¶
GET /v1/documents/{id}
Response (200):
{
"data": {
"id": "doc-uuid",
"client_id": "client-uuid",
"return_id": "return-uuid",
"tax_year": 2024,
"document_type": "W-2",
"filename": "W2_Employer_2024.pdf",
"file_size": 125000,
"mime_type": "application/pdf",
"status": "extracted",
"extraction": {
"id": "extraction-uuid",
"status": "verified",
"overall_confidence": 0.95,
"fields": [
{
"field_name": "employer_name",
"value": "Acme Corporation",
"confidence": 0.99,
"needs_review": false
},
{
"field_name": "wages",
"value": "75000.00",
"confidence": 0.97,
"needs_review": false
},
{
"field_name": "federal_withholding",
"value": "12500.00",
"confidence": 0.85,
"needs_review": true
}
]
},
"uploaded_at": "2024-12-20T10:00:00Z"
}
}
6.3 Upload Document¶
POST /v1/documents
Content-Type: multipart/form-data
Form Fields:
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | Document file |
client_id |
uuid | Yes | Client ID |
return_id |
uuid | No | Return ID (optional) |
tax_year |
integer | Yes | Tax year |
document_type |
string | No | Type hint (auto-classified if omitted) |
Response (201):
{
"data": {
"id": "new-doc-uuid",
"status": "processing",
"filename": "W2_2024.pdf",
"uploaded_at": "2024-12-23T11:30:00Z"
}
}
6.4 Download Document¶
GET /v1/documents/{id}/download
Response (200): Binary file with appropriate Content-Type
6.5 Update Document Metadata¶
PATCH /v1/documents/{id}
Permissions: Admin, EA/CPA, Reviewer, Preparer
Request:
Response (200): Updated document object
6.6 Delete Document (Soft)¶
DELETE /v1/documents/{id}
Permissions: Admin, EA/CPA
Notes: Soft delete only. Documents linked to filed returns cannot be deleted.
Response (204): No content
6.7 Update Extraction Field¶
PATCH /v1/documents/{doc_id}/extraction/fields/{field_id}
Permissions: Admin, EA/CPA, Reviewer, Preparer
Request:
Response (200): Updated field object
6.8 Delete Extraction¶
DELETE /v1/documents/{id}/extraction
Permissions: Admin, EA/CPA
Deletes extraction data for a document, allowing re-extraction.
Response (204): No content
6.9 Document Checklist¶
GET /v1/returns/{id}/documents/checklist
Returns expected documents based on prior year and current submissions.
Response (200):
{
"data": {
"expected": [
{
"document_type": "W-2",
"description": "W-2 from Acme Corporation",
"status": "received",
"document_id": "doc-uuid"
},
{
"document_type": "1099-DIV",
"description": "1099-DIV from Fidelity (based on prior year)",
"status": "missing",
"document_id": null
}
],
"unexpected": [
{
"document_type": "1099-INT",
"description": "1099-INT from New Bank",
"document_id": "doc-uuid-2"
}
]
}
}
6.10 Pending Documents (Upload-First Flow)¶
Upload documents before creating a client. Documents are stored in a pending state until assigned.
Upload Pending Document¶
POST /v1/pending-documents
Content-Type: multipart/form-data
Form Fields:
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | Document file |
batch_id |
string | Yes | Batch identifier for grouping |
Response (201):
{
"data": {
"id": "pending-doc-uuid",
"upload_batch_id": "batch-123",
"original_filename": "W2_2024.pdf",
"file_size_bytes": 125000,
"mime_type": "application/pdf",
"document_type": "W-2",
"tax_year": 2024,
"s3_key": "pending/batch-123/W2_2024.pdf",
"uploaded_at": "2024-12-20T10:00:00Z"
}
}
List Pending Batches¶
GET /v1/pending-documents/batches
Response (200):
{
"data": [
{
"batch_id": "batch-123",
"document_count": 3,
"uploaded_at": "2024-12-20T10:00:00Z",
"documents": [
{
"id": "pending-doc-uuid",
"original_filename": "W2_2024.pdf",
"document_type": "W-2",
"tax_year": 2024
}
]
}
]
}
Create Client from Batch¶
POST /v1/batch/{batch_id}/create-client
Creates a client, return, and moves pending documents to the new return.
Request:
{
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@example.com",
"phone": "+1-555-123-4567",
"tax_year": 2024,
"return_type": "individual"
}
Response (201):
{
"data": {
"client": {
"id": "client-uuid",
"account_number": "20241220-0001",
"first_name": "John",
"last_name": "Smith"
},
"return": {
"id": "return-uuid",
"tax_year": 2024,
"return_type": "individual",
"status": "intake"
},
"documents_assigned": 3
}
}
7. Questions API¶
Client questions generated by AI or preparer.
7.1 List Questions¶
GET /v1/returns/{id}/questions
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status (pending, answered, skipped) |
Response (200):
{
"data": [
{
"id": "question-uuid",
"return_id": "return-uuid",
"question_text": "Did you sell any stocks or investments in 2024?",
"context": "We noticed interest income but no capital gains reported",
"priority": "high",
"status": "pending",
"source": "ai_generated",
"created_by": null,
"created_at": "2024-12-22T14:00:00Z",
"answered_at": null,
"answer_text": null
}
]
}
7.2 Get Question¶
GET /v1/returns/{id}/questions/{question_id}
Response (200):
{
"data": {
"id": "question-uuid",
"return_id": "return-uuid",
"question_text": "Did you work from home in 2024?",
"context": "For home office deduction",
"category": "deduction_clarification",
"source": "ai_generated",
"status": "answered",
"created_at": "2024-12-22T14:00:00Z",
"answered_at": "2024-12-22T15:30:00Z",
"answer_text": "Yes, 3 days per week on average",
"answer_attachments": []
}
}
7.3 Create Question¶
POST /v1/returns/{id}/questions
Permissions: Admin, EA/CPA, Reviewer, Preparer
Request:
{
"question_text": "Please confirm your home office square footage",
"context": "For home office deduction calculation",
"priority": "medium"
}
7.4 Answer Question (Client)¶
POST /v1/returns/{id}/questions/{question_id}/answer
Permissions: Client (own return)
Request:
7.5 Skip Question¶
POST /v1/returns/{id}/questions/{question_id}/skip
Permissions: Admin, EA/CPA, Reviewer, Preparer
Request:
8. Messages API¶
Portal messaging between staff and clients.
8.1 List Messages¶
GET /v1/clients/{id}/messages
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
return_id |
uuid | Filter by return |
direction |
string | inbound, outbound, or both |
Response (200):
{
"data": [
{
"id": "message-uuid",
"client_id": "client-uuid",
"return_id": "return-uuid",
"direction": "outbound",
"sender_type": "staff",
"sender_id": "preparer-uuid",
"sender_name": "Sarah Preparer",
"subject": "Missing document needed",
"body": "Hello John, we need your 1099-B from...",
"read_at": "2024-12-22T16:30:00Z",
"created_at": "2024-12-22T14:00:00Z"
}
]
}
8.2 Send Message¶
POST /v1/clients/{id}/messages
Permissions: Admin, EA/CPA, Reviewer, Preparer (if assigned), Client (own)
Request:
{
"return_id": "return-uuid",
"subject": "Question about your return",
"body": "Hello, I wanted to follow up on...",
"notify_email": true
}
8.3 Mark as Read¶
POST /v1/clients/{id}/messages/{message_id}/read
Response (200):
9. Invoices API¶
9.1 List Invoices¶
GET /v1/invoices
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
client_id |
uuid | Filter by client |
return_id |
uuid | Filter by return |
status |
string | Filter by status (draft, sent, paid, overdue) |
Response (200):
{
"data": [
{
"id": "invoice-uuid",
"invoice_number": "INV-2024-00042",
"client_id": "client-uuid",
"return_id": "return-uuid",
"status": "sent",
"amount": 450.00,
"tax": 0.00,
"total": 450.00,
"amount_paid": 0.00,
"amount_due": 450.00,
"due_date": "2025-01-15",
"payment_link": "https://pay.stripe.com/...",
"line_items": [
{
"description": "2024 Individual Tax Return (1040)",
"quantity": 1,
"unit_price": 400.00,
"amount": 400.00
},
{
"description": "Schedule C - Business Income",
"quantity": 1,
"unit_price": 50.00,
"amount": 50.00
}
],
"created_at": "2024-12-22T10:00:00Z",
"sent_at": "2024-12-22T10:05:00Z"
}
]
}
9.2 Get Invoice¶
GET /v1/invoices/{id}
Response (200):
{
"data": {
"id": "invoice-uuid",
"client_id": "client-uuid",
"return_id": "return-uuid",
"invoice_number": "INV-2024-0001",
"status": "sent",
"total_amount": 450.00,
"amount_paid": 0.00,
"balance_due": 450.00,
"due_date": "2025-01-15",
"line_items": [
{
"description": "2024 Individual Tax Return (1040)",
"quantity": 1,
"unit_price": 400.00,
"amount": 400.00
},
{
"description": "Schedule C - Business Income",
"quantity": 1,
"unit_price": 50.00,
"amount": 50.00
}
],
"payments": [],
"created_at": "2024-12-22T10:00:00Z",
"sent_at": "2024-12-22T10:05:00Z"
}
}
9.3 Create Invoice¶
POST /v1/invoices
Permissions: Admin, EA/CPA
Request:
{
"client_id": "client-uuid",
"return_id": "return-uuid",
"due_date": "2025-01-15",
"line_items": [
{
"description": "2024 Individual Tax Return (1040)",
"quantity": 1,
"unit_price": 400.00
}
]
}
Response (201): Created invoice object
9.4 Update Invoice¶
PATCH /v1/invoices/{id}
Permissions: Admin, EA/CPA
Notes: Only draft invoices can be updated. Sent invoices must be voided and recreated.
Request:
{
"due_date": "2025-01-31",
"line_items": [
{
"description": "2024 Individual Tax Return (1040)",
"quantity": 1,
"unit_price": 450.00
}
]
}
Response (200): Updated invoice object
9.5 Send Invoice¶
POST /v1/invoices/{id}/send
Permissions: Admin, EA/CPA
Sends invoice to client via email with payment link (draft invoices only).
Response (200):
{
"data": {
"id": "invoice-uuid",
"status": "sent",
"sent_at": "2024-12-23T12:30:00Z",
"payment_link": "https://pay.stripe.com/..."
}
}
9.6 Record Payment¶
POST /v1/invoices/{id}/payments
Request:
9.7 List Payments¶
GET /v1/invoices/{id}/payments
Response (200):
{
"data": [
{
"id": "payment-uuid",
"invoice_id": "invoice-uuid",
"amount": 450.00,
"payment_method": "credit_card",
"status": "completed",
"stripe_payment_intent_id": "pi_xxxxx",
"processed_at": "2024-12-23T14:00:00Z",
"created_at": "2024-12-23T14:00:00Z"
}
],
"meta": {
"total_paid": 450.00,
"balance_due": 0.00
}
}
10. Engagements API¶
10.1 List Engagements¶
GET /v1/engagements
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
client_id |
uuid | Filter by client |
tax_year |
integer | Filter by tax year |
status |
string | Filter by status |
10.2 Get Engagement¶
GET /v1/engagements/{id}
Permissions: Admin, EA/CPA, Reviewer, Preparer (if assigned to client)
Response (200):
{
"data": {
"id": "engagement-uuid",
"client_id": "client-uuid",
"tax_year": 2024,
"engagement_type": "tax_prep",
"services": ["1040", "schedule_c"],
"status": "signed",
"fee_structure": {
"type": "fixed",
"base_fee": 400.00,
"additional_forms": 50.00
},
"signed_at": "2024-01-15T10:30:00Z",
"document_url": "/v1/engagements/engagement-uuid/document",
"created_at": "2024-01-10T09:00:00Z"
}
}
10.3 Create Engagement¶
POST /v1/engagements
Permissions: Admin, EA/CPA, Reviewer
Request:
{
"client_id": "client-uuid",
"tax_year": 2024,
"engagement_type": "tax_prep",
"services": ["1040", "schedule_c"],
"fee_structure": {
"type": "fixed",
"base_fee": 400.00,
"additional_forms": 50.00
}
}
10.4 Update Engagement¶
PATCH /v1/engagements/{id}
Permissions: Admin, EA/CPA, Reviewer
Guard Conditions:
- Status must not be signed (engagement already executed)
Request:
{
"services": ["1040", "schedule_c", "schedule_e"],
"fee_structure": {
"type": "fixed",
"base_fee": 500.00,
"additional_forms": 50.00
}
}
Response (200): Updated engagement object
10.5 Delete Engagement¶
DELETE /v1/engagements/{id}
Permissions: Admin, EA/CPA
Guard Conditions:
- Status must be draft (cannot delete signed engagements)
Response (204): No content
10.6 Send for Signature¶
POST /v1/engagements/{id}/send
Generates engagement letter and sends via Google Workspace for signature.
Response (200):
{
"data": {
"id": "engagement-uuid",
"status": "pending_signature",
"signature_request_id": "google-sig-uuid",
"sent_at": "2024-12-23T13:00:00Z"
}
}
10.7 Get Signed Document¶
GET /v1/engagements/{id}/document
Returns signed engagement letter PDF.
10.8 Form 7216 Consent¶
IRS Form 7216 consent for disclosure of tax return information to third parties.
List Consents¶
GET /v1/clients/{id}/consents
Response (200):
{
"data": [
{
"id": "consent-uuid",
"client_id": "client-uuid",
"tax_year": 2024,
"consent_scope": "SurePrep document processing",
"status": "signed",
"created_at": "2024-01-15T10:00:00Z",
"signed_at": "2024-01-15T10:05:00Z",
"expires_at": "2025-01-15T10:05:00Z"
}
]
}
Create Consent Request¶
POST /v1/clients/{id}/consents
Permissions: Admin, EA/CPA, Reviewer
Request:
{
"tax_year": 2024,
"consent_scope": "SurePrep document processing",
"third_party_name": "SurePrep LLC",
"disclosure_purpose": "Document OCR and data extraction for tax preparation"
}
Response (201): Created consent object with status pending
Get Consent¶
GET /v1/consents/{id}
Response (200): Full consent object including signature details
Send for Signature¶
POST /v1/consents/{id}/send
Sends Form 7216 consent to client via Google Workspace for e-signature.
Response (200):
{
"data": {
"id": "consent-uuid",
"status": "sent",
"signature_request_id": "google-sig-uuid",
"sent_at": "2024-01-15T10:00:00Z"
}
}
Revoke Consent¶
POST /v1/consents/{id}/revoke
Permissions: Admin, EA/CPA
Revokes an active consent. Creates audit trail entry.
Response (200):
{
"data": {
"id": "consent-uuid",
"status": "revoked",
"revoked_at": "2024-06-15T14:00:00Z",
"revoked_by": "user-uuid"
}
}
11. E-Filing API¶
11.1 List E-File Transmissions¶
GET /v1/returns/{id}/efiling
Response (200):
{
"data": [
{
"id": "transmission-uuid",
"return_id": "return-uuid",
"jurisdiction": "federal",
"status": "accepted",
"transmitted_at": "2024-12-23T09:00:00Z",
"acknowledged_at": "2024-12-23T12:30:00Z",
"confirmation_number": "IRS123456789",
"acceptance_date": "2024-12-23"
},
{
"id": "transmission-uuid-2",
"return_id": "return-uuid",
"jurisdiction": "CA",
"status": "pending",
"transmitted_at": "2024-12-23T09:00:00Z",
"acknowledged_at": null
}
]
}
11.2 Get Transmission¶
GET /v1/returns/{id}/efiling/{transmission_id}
Response (200):
{
"data": {
"id": "transmission-uuid",
"return_id": "return-uuid",
"jurisdiction": "federal",
"transmission_type": "original",
"status": "transmitted",
"transmitted_at": "2024-12-23T09:00:00Z",
"acknowledgement": {
"id": "ack-uuid",
"ack_type": "accepted",
"confirmation_number": "IRS123456789",
"received_at": "2024-12-23T12:30:00Z"
},
"rejection": null
}
}
11.3 Transmit Return¶
POST /v1/returns/{id}/efiling/transmit
Permissions: Admin, EA/CPA
Guard Conditions:
- Return status must be ready_to_file
- Signed Form 8879 must be on file
- All required forms must be complete
Request:
Response (202):
{
"data": {
"transmissions": [
{
"id": "transmission-uuid",
"jurisdiction": "federal",
"status": "transmitting"
},
{
"id": "transmission-uuid-2",
"jurisdiction": "CA",
"status": "transmitting"
}
]
}
}
11.4 Get Rejection Details¶
GET /v1/returns/{id}/efiling/{transmission_id}/rejections
Response (200):
{
"data": {
"transmission_id": "transmission-uuid",
"jurisdiction": "federal",
"rejections": [
{
"id": "rejection-uuid",
"error_code": "IND-031-04",
"category": "data_mismatch",
"description": "SSN/Name mismatch with SSA records",
"resolution_guidance": "Verify taxpayer SSN and name match Social Security card exactly",
"auto_correctable": false,
"created_at": "2024-12-23T12:35:00Z"
}
]
}
}
11.5 Resubmit After Rejection¶
POST /v1/returns/{id}/efiling/{transmission_id}/resubmit
Permissions: Admin, EA/CPA
Request:
11.6 Estimated Tax Payments¶
Manage quarterly estimated tax payments for clients.
List Estimated Payments¶
GET /v1/returns/{id}/estimated-payments
Response (200):
{
"data": [
{
"id": "payment-uuid",
"return_id": "return-uuid",
"quarter": 1,
"due_date": "2025-04-15",
"federal_amount": 5000.00,
"state_amount": 1500.00,
"status": "scheduled",
"reminder_sent": false
},
{
"id": "payment-uuid-2",
"quarter": 2,
"due_date": "2025-06-15",
"federal_amount": 5000.00,
"state_amount": 1500.00,
"status": "scheduled",
"reminder_sent": false
}
]
}
Create Estimated Payment Schedule¶
POST /v1/returns/{id}/estimated-payments
Permissions: Admin, EA/CPA, Preparer
Request:
{
"tax_year": 2025,
"federal_annual": 20000.00,
"state_annual": 6000.00,
"payment_method": "equal_quarterly"
}
Response (201): Created payment schedule with 4 quarterly payments
Update Payment¶
PATCH /v1/estimated-payments/{id}
Request:
Response (200): Updated payment object
Send Reminder¶
POST /v1/estimated-payments/{id}/remind
Sends reminder to client about upcoming estimated tax payment.
Request:
Response (200):
{
"data": {
"id": "payment-uuid",
"reminder_sent": true,
"reminder_sent_at": "2024-04-01T10:00:00Z",
"reminder_type": "14_day"
}
}
Mark Payment Confirmed¶
POST /v1/estimated-payments/{id}/confirm
Client confirms payment was made.
Request:
Response (200): Updated payment with status confirmed_paid
Delete Estimated Payment¶
DELETE /v1/estimated-payments/{id}
Permissions: Admin, EA/CPA
Guard Conditions:
- Payment status must not be confirmed_paid
Cancels a scheduled estimated tax payment.
Response (204): No content
12. Identity Verification API¶
12.1 Initiate Verification¶
POST /v1/clients/{id}/identity/verify
Request:
Response (201):
{
"data": {
"verification_id": "verification-uuid",
"status": "pending",
"current_step": "email",
"steps": [
{"step": "email", "status": "pending"},
{"step": "phone", "status": "pending"},
{"step": "government_id", "status": "pending"}
]
}
}
12.2 Verify Email¶
POST /v1/identity/{verification_id}/email/verify
Request:
12.3 Verify Phone¶
POST /v1/identity/{verification_id}/phone/send
Request:
POST /v1/identity/{verification_id}/phone/verify
Request:
12.4 Submit Government ID¶
POST /v1/identity/{verification_id}/government-id
Redirects to Persona or returns embed URL.
Response (200):
{
"data": {
"persona_inquiry_url": "https://withpersona.com/verify?inquiry-id=...",
"expires_at": "2024-12-23T14:00:00Z"
}
}
12.5 Get Verification Status¶
GET /v1/identity/{verification_id}
Response (200):
{
"data": {
"verification_id": "verification-uuid",
"client_id": "client-uuid",
"tier": 2,
"status": "completed",
"confidence_score": 0.92,
"completed_at": "2024-12-23T13:45:00Z",
"steps": [
{"step": "email", "status": "completed"},
{"step": "phone", "status": "completed"},
{"step": "government_id", "status": "completed", "confidence": 0.92}
]
}
}
12.6 Schedule Video Verification (Tier 3)¶
POST /v1/identity/{verification_id}/video/schedule
Request:
Response (200):
{
"data": {
"session_id": "meet-session-uuid",
"scheduled_time": "2024-12-24T10:00:00Z",
"meet_link": "https://meet.google.com/xxx-xxxx-xxx",
"calendar_invite_sent": true
}
}
13. Webhooks API¶
13.1 Webhook Endpoints (Inbound)¶
The system receives webhooks from external providers.
Stripe Webhooks¶
POST /v1/webhooks/stripe
Headers:
Events Handled:
- payment_intent.succeeded
- payment_intent.payment_failed
- checkout.session.completed
Persona Webhooks¶
POST /v1/webhooks/persona
Headers:
Events Handled:
- inquiry.completed
- inquiry.failed
- inquiry.expired
SmartVault Webhooks¶
POST /v1/webhooks/smartvault
Events Handled:
- document.uploaded
- folder.created
SurePrep Webhooks¶
POST /v1/webhooks/sureprep
Events Handled:
- binder.submitted - Binder submitted for processing
- binder.processing_complete - OCR/extraction finished
- binder.verification_complete - Manual verification done
- document.uploaded - Document added to binder
- extraction.ready - Extracted data available
Google Workspace Webhooks¶
POST /v1/webhooks/google
Events Handled:
- signature.completed
- signature.declined
- calendar.event.updated
E-Filing Webhooks¶
POST /v1/webhooks/efiling
Events Handled:
- transmission.accepted - Return accepted by IRS/state
- transmission.rejected - Return rejected with error codes
- transmission.pending - Return awaiting acknowledgment
13.2 Webhook Signature Verification¶
All inbound webhooks are verified:
def verify_stripe_webhook(payload: bytes, signature: str) -> bool:
"""Verify Stripe webhook signature using HMAC."""
pass
def verify_persona_webhook(payload: bytes, signature: str) -> bool:
"""Verify Persona webhook signature."""
pass
13.3 Webhook Delivery (Outbound)¶
Future: System can send webhooks to external systems.
POST /v1/admin/webhooks
Request:
{
"url": "https://partner.example.com/webhook",
"events": ["return.status.changed", "document.uploaded"],
"secret": "webhook-signing-secret"
}
14. Admin API¶
14.1 Users¶
List Users¶
GET /v1/admin/users
Permissions: Admin only
Create User¶
POST /v1/admin/users
Request:
{
"email": "newpreparer@firm.com",
"full_name": "New Preparer",
"role": "preparer",
"ptin": "P12345678"
}
Update User¶
PATCH /v1/admin/users/{id}
Deactivate User¶
POST /v1/admin/users/{id}/deactivate
14.2 System Configuration¶
Get Configuration¶
GET /v1/admin/config
Update Configuration¶
PATCH /v1/admin/config
Request:
14.3 Audit Logs¶
Query Audit Logs¶
GET /v1/admin/audit
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
user_id |
uuid | Filter by user |
client_id |
uuid | Filter by client |
event_type |
string | Filter by event type |
start_date |
datetime | Start of date range |
end_date |
datetime | End of date range |
Export Audit Logs¶
POST /v1/admin/audit/export
Request:
{
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-12-31T23:59:59Z",
"format": "json",
"filters": {
"client_id": "client-uuid"
}
}
Response (202):
14.4 System Health¶
Health Check¶
GET /v1/health
No authentication required
Response (200):
Detailed Health¶
GET /v1/admin/health/detailed
Permissions: Admin only
Response (200):
{
"status": "healthy",
"components": {
"database": {"status": "healthy", "latency_ms": 5},
"redis": {"status": "healthy", "latency_ms": 2},
"s3": {"status": "healthy"},
"bedrock": {"status": "healthy"},
"stripe": {"status": "healthy"},
"persona": {"status": "healthy"}
}
}
Appendix A: Enum Values¶
Client Type¶
individualbusinesstrustnonprofit
Return Type¶
1040- Individual1120- C Corporation1120S- S Corporation1065- Partnership1041- Trust/Estate990- Nonprofit706- Gift Tax Return709- Generation Skipping Transfer Tax
Filing Status¶
singlemarried_jointmarried_separatehead_of_householdqualifying_widow
Return Status (Workflow)¶
intakedocuments_pendingready_for_prepai_analysisin_preppending_client_responseready_for_reviewin_reviewrevisions_neededapprovedpending_signatureready_to_filefiledacceptedrejectedcompleteneeds_review
Document Type¶
W-2- Wage and Tax StatementW-2G- Gambling Winnings1099-INT- Interest Income1099-DIV- Dividends and Distributions1099-B- Broker Transactions1099-R- Retirement Distributions1099-MISC- Miscellaneous Income1099-NEC- Nonemployee Compensation1099-K- Payment Card Transactions1099-G- Government PaymentsSSA-1099- Social Security BenefitsK-1_1065- Schedule K-1 (Partnership)K-1_1120S- Schedule K-1 (S Corporation)K-1_1041- Schedule K-1 (Trust/Estate)1098- Mortgage Interest1098-E- Student Loan Interest1098-T- Tuition StatementBANK_STATEMENT- Bank StatementBROKERAGE_STATEMENT- Brokerage StatementPROPERTY_TAX- Property Tax StatementENGAGEMENT_LETTER- Engagement LetterFORM_8879- IRS e-file Signature AuthorizationFORM_7216- Consent for DisclosureDRAFT_RETURN- Draft Tax ReturnFINAL_RETURN- Final Tax ReturnEFILE_CONFIRMATION- E-file ConfirmationID_DOCUMENT- Identity DocumentOTHER- Other Document
User Role (Staff)¶
adminea_cpareviewerpreparer
Note: Clients authenticate via tiered identity verification and receive JWT tokens with client_id claims. They do not have a database user role. See SECURITY_DESIGN.md Section 2.2.
Appendix B: Internal Resources¶
The following database tables are internal resources accessed only through related API endpoints or internal services. They do not have dedicated REST endpoints.
| Resource | Table | Access Method |
|---|---|---|
| Preparer Notes | preparer_notes |
Included in GET /v1/returns/{id} response for staff |
| Workflow State | workflow_state |
Via GET /v1/returns/{id}/workflow/state |
| Workflow History | workflow_history |
Included in workflow state response |
| Extracted Fields | extracted_field |
Included in GET /v1/documents/{id} extraction data |
| Audit Log | audit_log |
Admin-only via GET /v1/admin/audit-logs |
| PTIN Records | ptin_record |
Admin-only via GET /v1/admin/users/{id} |
Preparer Notes: Staff can add, view, and update notes on returns via the return detail endpoint. Notes are stored in preparer_notes table with return_id, document_id (optional), and note_text fields.
GET /v1/returns/{id} → includes preparer_notes array
PATCH /v1/returns/{id} → can update notes via nested object
Document History¶
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2024-12-23 | Don McCarty | Initial API specification |
This document defines the REST API for Tax Practice AI. Implementation should follow these specifications exactly to ensure consistency across clients.