Offers Management API
Complete offer lifecycle management with Inquiry integration and acceptance workflow
Overview
The Offers API manages the complete lifecycle of contractor offers linked to Inquiries. Multiple contractors can submit offers for the same inquiry. When a client accepts one offer, all other offers for that inquiry are automatically expired and all contractors are notified of the outcome.
Inquiry-Based Workflow
1. Client posts an inquiry
2. Multiple contractors submit offers (linked to inquiry_id)
3. Client reviews all offers
4. Client accepts one offer → All others auto-expire
5. All contractors receive email notifications
Core Features
- Inquiry-based linking
- Multi-contractor support
- Acceptance workflow
- Auto-expire competing offers
- Email notifications
Offer Status
- Draft - Not yet sent
- Sent - Delivered to client
- Viewed - Client has seen it
- Accepted - Client accepted
- Rejected - Client rejected
- Expired - Another offer accepted
Offer Line Types
- Product - Materials/products
- Labor - Work hours
- Travel - Travel costs
- Other - Misc. costs
- Auto-calc VAT & totals
Notifications
- New offer sent to client
- Acceptance notification
- Rejection notification
- Expiration notification
Attachments
- Upload files per offer
- PDF, images, Office docs
- Max 10 MB per file
- Private local storage
- Secure download endpoint
| Method | Endpoint | Description | Requirements |
|---|---|---|---|
| POST | /api/offers/send | Submit a new offer from contractor to client (linked to an inquiry) |
|
| GET | /api/offers/list?inquiry_id={id} | List all offers for a specific inquiry |
|
| GET | /api/offers/client?client_id={id} | List all offers visible to a specific client |
|
| GET | /api/offers/{id} | Get details of a specific offer (auto-marks as viewed) |
|
| POST | /api/offers/{id}/accept | Accept an offer (expires all other offers for the same inquiry) |
|
| POST | /api/offers/{id}/reject | Reject an offer |
|
| GET | /api/offers/{id}/attachments | List all file attachments for an offer |
|
| POST | /api/offers/{id}/attachments | Upload a file attachment to an offer (multipart/form-data) |
|
| GET | /api/offers/{id}/attachments/{attachmentId}/download | Download an attachment file |
|
| DELETE | /api/offers/{id}/attachments/{attachmentId} | Delete an attachment (removes file from disk) |
|
Request Examples
1. Send Offer for an Inquiry
POST /api/offers/send
POST /api/offers/send
Note: Each line automatically calculates discount_amount, subtotal, vat_amount, and total based on quantity, unit_price, discount_percentage, and vat_percentage. The offer's overall subtotal, tax_amount, and total are calculated from all lines.
Response - Offer Sent (201 Created)
Get Offer Details with Lines
GET /api/offers/{id}
2. List All Offers for an Inquiry
GET /api/offers/list?inquiry_id=5
3. Accept an Offer
POST /api/offers/{id}/accept
Response:
Note: Accepting an offer automatically expires all other offers for the same inquiry
and sends email notifications to all contractors. User data (names, emails) is resolved
by the UserHub proxy and returned in the top-level users map in the response.
4. Reject an Offer
POST /api/offers/{id}/reject
Response:
Email Notifications
Contractors receive different email notifications based on offer status: