diff --git a/API_ENDPOINTS.md b/API_ENDPOINTS.md new file mode 100644 index 0000000..4e71c60 --- /dev/null +++ b/API_ENDPOINTS.md @@ -0,0 +1,331 @@ +# DoliMiddlewareApi - API Reference + +BFF (Backend For Frontend) between the Vue.js frontend and Dolibarr ERP. + +Base URL: `http://localhost:5269` (dev) / `http://localhost:5000` (Docker) + +Auth: All endpoints except `POST /api/Auth/login` require a JWT Bearer token. + +--- + +## Authentication + +### POST /api/Auth/login +Login and get JWT token. + +**Request:** +```json +{ + "username": "admin", + "password": "12345678" +} +``` + +**Response:** `200 OK` +```json +{ + "token": "eyJhbGciOiJIUzI1NiIs..." +} +``` + +After login, include the token in all requests: `Authorization: Bearer ` + +--- + +## Clients + +### GET /api/Clients +List clients with their contacts. + +**Query params:** `limit` (default 50), `page` (default 1) + +**Response:** `200 OK` +```json +[ + { + "id": 1, + "name": "Client Name", + "codeClient": "CU0001", + "typentCode": null, + "status": "1", + "email": "client@example.com", + "phone": "+34600000000", + "contacts": [ + { "id": 1, "lastname": "Garcia", "firstname": "Ana", "email": "ana@example.com", "phonePro": "...", "phonePerso": "...", "phoneMobile": "...", "clientId": 1 } + ] + } +] +``` + +### GET /api/Clients/{id} +Get client detail with contacts and full address info. + +**Response:** `200 OK` +```json +{ + "id": 1, + "name": "Client Name", + "codeClient": "CU0001", + "typentCode": null, + "status": "1", + "email": "client@example.com", + "phone": "+34600000000", + "address": "Calle Mayor 1", + "town": "Madrid", + "zip": "28001", + "countryCode": "ES", + "vatNumber": "B12345678", + "url": null, + "notePublic": null, + "notePrivate": null, + "contacts": [...] +} +``` + +### POST /api/Clients +Create a new client. + +**Request:** +```json +{ + "name": "New Client", + "address": "Calle Example 5", + "zip": "28001", + "town": "Madrid", + "phone": "+34600000000", + "email": "client@example.com", + "countryCode": "ES", + "vatNumber": null, + "url": null, + "notePublic": null, + "notePrivate": null +} +``` + +**Response:** `201 Created` → Returns new client ID (int) + +### PUT /api/Clients/{id} +Update a client. Only send fields you want to change. + +**Request:** +```json +{ + "name": "Updated Name", + "phone": "+34611111111" +} +``` + +**Response:** `204 No Content` + +### DELETE /api/Clients/{id} +Delete a client. + +**Response:** `204 No Content` + +--- + +## Contacts + +### GET /api/Contacts +List contacts. Optionally filter by client. + +**Query params:** `limit` (default 50), `page` (default 1), `thirdpartyIds` (comma-separated client IDs) + +Example: `GET /api/Contacts?thirdpartyIds=1,2&limit=100` + +**Response:** `200 OK` +```json +[ + { "id": 1, "lastname": "Garcia", "firstname": "Ana", "email": "ana@example.com", "phonePro": "...", "phonePerso": null, "phoneMobile": "...", "clientId": 1 } +] +``` + +### GET /api/Contacts/{id} +Get contact detail with address and civility info. + +**Response:** `200 OK` +```json +{ + "id": 1, + "lastname": "Garcia", + "firstname": "Ana", + "email": "ana@example.com", + "phonePro": "+34910000000", + "phonePerso": null, + "phoneMobile": "+34600000001", + "clientId": 1, + "address": "Calle Example 5", + "town": "Madrid", + "zip": "28001", + "civilityCode": null, + "status": "active" +} +``` + +### GET /api/Contacts/email/{email} +Find a contact by email address. + +**Response:** `200 OK` → Same as `GET /api/Contacts/{id}` + +### POST /api/Contacts +Create a contact. + +**Request:** +```json +{ + "lastname": "Garcia", + "firstname": "Ana", + "clientId": 1, + "email": "ana@example.com", + "phonePro": "+34910000000", + "phoneMobile": "+34600000001", + "address": "Calle Example 5", + "zip": "28001", + "town": "Madrid" +} +``` + +**Response:** `201 Created` → Returns new contact ID (int) + +### PUT /api/Contacts/{id} +Update a contact. Only send fields to change. + +**Response:** `204 No Content` + +### DELETE /api/Contacts/{id} +Delete a contact. + +**Response:** `204 No Content` + +--- + +## Invoices + +### GET /api/Invoices +List invoices. + +**Query params:** `limit` (default 50), `page` (default 1), `status` (draft/unpaid/paid), `search` (ref search) + +### GET /api/Invoices/{id} +Get invoice detail with lines, totals, and payment info. + +### POST /api/Invoices +Create invoice. See existing frontend for request body format. + +### PUT /api/Invoices/{id} +Update invoice (expireDate, notePublic, notePrivate, number). + +### PATCH /api/Invoices/{id}/status +Change invoice status: `{ "status": "draft" | "unpaid" | "paid" }` + +### POST /api/Invoices/{id}/validate +Validate (confirm) a draft invoice. + +### DELETE /api/Invoices/{id} +Delete a draft invoice. + +### POST /api/Invoices/{id}/lines +Add a line to a draft invoice. + +**Request:** +```json +{ "description": "Service", "quantity": 1, "unitPrice": 100, "taxRate": 21 } +``` + +### PUT /api/Invoices/{invoiceId}/lines/{lineId} +Update a line in a draft invoice. + +**Request:** +```json +{ "description": "Updated desc", "quantity": 2, "unitPrice": 150, "taxRate": 10 } +``` +All fields optional — only send what you want to change. + +### DELETE /api/Invoices/{invoiceId}/lines/{lineId} +Delete a line from a draft invoice. + +### GET /api/Invoices/{id}/payments +List payments for an invoice. + +### POST /api/Invoices/{id}/payments +Add payment to an invoice. + +### GET /api/Invoices/templates +List invoice templates (recurring invoices in Dolibarr). + +--- + +## Documents + +### GET /api/Document/invoice/{invoiceRef}/pdf +Download/build a PDF for an invoice. Returns `application/pdf` file. + +### GET /api/Document/list +List documents for an element. + +**Query params:** `modulePart` (default "invoice"), `refId` (required — invoice ref or societe id) + +### GET /api/Document/download +Download a document file. + +**Query params:** `modulePart` (default "invoice"), `file` (required — file path in Dolibarr) + +--- + +## Setup (Reference Data) + +These endpoints return dictionary/reference data from Dolibarr, useful for populating dropdowns and selectors. + +### GET /api/Setup/payment-types +Returns payment type options (Cash, Cheque, Credit card, etc.) + +```json +[ + { "id": "4", "code": "LIQ", "label": "Cash", "type": "2" }, + { "id": "6", "code": "CB", "label": "Credit card", "type": "2" }, + { "id": "7", "code": "CHQ", "label": "Cheque", "type": "2" } +] +``` + +### GET /api/Setup/countries +Returns country list with ISO codes. + +### GET /api/Setup/civilities +Returns civility titles (Mr, Mrs, etc.). + +### GET /api/Setup/contact-types +Returns contact type labels. + +### GET /api/Setup/payment-terms +Returns payment terms (Due on receipt, 30 days, etc.). + +### GET /api/Setup/company +Returns your company info (name, address, VAT number, etc.). + +--- + +## Deployment + +### Docker Compose + +1. Copy `.env.example` to `.env` and set `JWT_SECRET` to a long random string +2. Run: `docker compose up -d` +3. BFF will be available at `http://localhost:5000` +4. Swagger UI at `http://localhost:5000/swagger` + +### Environment Variables + +| Variable | Required | Description | +|----------|----------|-------------| +| `Jwt__Secret` | Yes | JWT signing key, min 32 chars | +| `Dolibarr__ApiUrl` | Yes | Dolibarr API base URL (e.g. `http://dolibarr/api/index.php`) | +| `Cors__AllowedOrigins` | No | Semicolon-separated CORS origins. Empty = allow all | +| `ASPNETCORE_ENVIRONMENT` | No | `Production` or `Development` | + +### Frontend .env + +``` +VITE_API_BASE_URL=http://localhost:5000 +``` + +When connecting to the BFF in Docker, use `http://localhost:5000` (the BFF port), not the Dolibarr port directly. \ No newline at end of file