External Integrations
Proxima Invoice integrates with several external services across different phases.
Integration Map
Green = implemented, Gray = planned.
Gotenberg (Phase 1)
PDF generation service based on Chromium headless browser.
| Setting | Value |
|---|---|
| Endpoint | convert.prxm.uz |
| Protocol | HTTPS |
| API | POST /forms/chromium/convert/html |
| Timeout | 30 seconds |
| Retry | Max 3 attempts |
| Input | HTML file (multipart/form-data) |
| Output | PDF binary |
Configuration
INVOICE_PDF_CONVERTER_URL=https://convert.prxm.uz
INVOICE_PDF_CONVERTER_TIMEOUT=30s
Usage
The backend renders an HTML invoice template using Go's html/template, then sends it to Gotenberg:
POST /forms/chromium/convert/html
Content-Type: multipart/form-data
file=index.html
paperWidth=8.27
paperHeight=11.69
marginTop=0.5
marginBottom=0.5
marginLeft=0.5
marginRight=0.5
PlanFact (Phase 3) ✅
Accounting and financial planning platform. Invoices are synced as "shipments" after approval.
| Setting | Value |
|---|---|
| API Base | https://api.planfact.io/api/v1 |
| Auth | X-ApiKey header |
| Timeout | 10 seconds |
| Company ID | 146673 |
| Package | internal/services/planfact/ |
Configuration
INVOICE_PLANFACT_API_KEY=your-api-key
INVOICE_PLANFACT_COMPANY_ID=146673 # default
Sync Flow
On invoice approval, an async goroutine (30s timeout) performs:
Item Building by Deal Type
| Deal Type | Items |
|---|---|
| SUP | 1x support_product (base fee) + Nx hourly_product (if overtime) |
| HR | Nx hourly_product (count=total_hours, value=total_amount) |
| FP | Nx hourly_product (count=total_hours, value=total_amount) |
Product IDs
| Product | ID | Usage |
|---|---|---|
| Hourly Rate | b78ac753-0bbb-41aa-9408-b23700c9f2b4 | HR, FP, SUP overtime |
| Monthly Support | d9c144af-dd05-4f68-b136-b37100f12f8a | SUP base fee |
Manual Retry
If async sync fails (e.g., PlanFact is down), retry manually:
POST /api/v1/invoices/:id/sync-planfact
Only works on approved or sent invoices. Frontend shows a "Retry" button in the Integrations card.
Failure Handling
- Sync failures are recorded as
planfact_sync_failedevents ininvoice_events - Failures do not affect the approval result (async, fire-and-forget)
- Nil-safe: service disabled when
INVOICE_PLANFACT_API_KEYis empty
Cloudflare R2 (Phase 3) ✅
S3-compatible object storage for permanent PDF archival with public URL access.
| Setting | Value |
|---|---|
| Bucket | proxima-invoices |
| Domain | invoices.prxm.uz |
| Key format | invoices/{year}/{application_key}/Act_{display_number}.pdf |
| SDK | AWS SDK v2 (S3-compatible) |
| Timeout | 10 seconds |
| Package | internal/services/r2/ |
Configuration
INVOICE_R2_ACCOUNT_ID=your-cloudflare-account-id
INVOICE_R2_ACCESS_KEY=your-r2-access-key
INVOICE_R2_SECRET_KEY=your-r2-secret-key
INVOICE_R2_BUCKET=proxima-invoices # default
INVOICE_R2_PUBLIC_DOMAIN=invoices.prxm.uz # default
Upload Flow
On invoice approval, before the status transition transaction (best-effort):
- Fetch PDF data from the invoice record
- Build key:
invoices/{year}/{application_key}/Act_{display_number}.pdf - Upload via S3 PutObject to
https://{accountID}.r2.cloudflarestorage.com - Store
r2_storage_keyandr2_public_urlon the invoice record - If upload fails: log warning, continue with approval (PDF stays in DB)
Failure Handling
- R2 upload is best-effort — failures don't block approval
- PDF remains available from the database (
GET /invoices/:id/pdf) - Nil-safe: service disabled when R2 credentials are not set
- Frontend shows "Not uploaded" in the Integrations card when
r2_public_urlis empty
Didox.uz (Phase 4)
Uzbekistan's e-invoicing platform for B2B transactions. Required for local (UZS) invoices.
| Setting | Value |
|---|---|
| Purpose | Legal e-invoicing in Uzbekistan |
| Seller TIN | 309630523 (ProximaOps) |
| Document type | Service act |
Configuration
INVOICE_DIDOX_API_URL=https://api.didox.uz
INVOICE_DIDOX_API_KEY=your-api-key
INVOICE_DIDOX_SELLER_TIN=309630523
Flow
- Submit invoice document to Didox API
- Receive
didox_document_id - Track status via
didox_status(pending → accepted/rejected) - Receive webhook callbacks for status updates
Telegram (Phase 2) ✅
Optional notification bot for approval workflow events. Implemented and active.
| Setting | Value |
|---|---|
| Purpose | Notify managers when invoices are approved |
| Default | Disabled (enabled when both env vars are set) |
| API | Telegram Bot API (api.telegram.org) |
| Timeout | 15 seconds |
Configuration
INVOICE_TELEGRAM_BOT_TOKEN=your-bot-token
INVOICE_TELEGRAM_CHAT_ID=your-chat-id
When both variables are set, the Notifier is initialized at startup and injected into the invoice service. When either is empty, notifications are silently disabled.
Notifications
Currently implemented:
- Invoice approved: Sends PDF as a document attachment with caption "✅ Invoice APP-001 #42 approved by admin". Falls back to text message if PDF is unavailable or document send fails.
Notification is sent in a background goroutine after approval succeeds — failures are logged but never affect the approval result.
API Methods
| Method | Telegram API | Content-Type |
|---|---|---|
SendMessage | /bot{token}/sendMessage | application/json |
SendDocument | /bot{token}/sendDocument | multipart/form-data |
Timeout and Retry Policy
| Integration | Timeout | Max Retries | Retry On |
|---|---|---|---|
| Gotenberg | 30s | 3 | Network errors, 5xx |
| PlanFact | 10s | 3 | Network errors, 5xx |
| R2 | 10s | 3 | Network errors, 5xx |
| Didox | 10s | 3 | Network errors, 5xx |
| Telegram | 5s | 2 | Network errors |
Never retry: Validation errors (4xx), authentication errors (401/403).