Credit Line Requests API
All endpoints require a valid admin JWT token unless noted otherwise. Routes are prefixed per section below.
Authentication
Authorization: Bearer <token_admin>Role-based access is enforced via permissionMiddleware.canByName. Permissions required per endpoint are listed in the Permission column.
| Permission | Grants |
|---|---|
credit-line-requests | Read-only access (list, detail, downloads) |
credit-line-requests-manage | Mutating actions: status, details, document file upload, pagaré format upload |
credit-line-requests-review-documents | Document review: approve/reject documents (single + bulk) and validate the signed pagaré |
credit-line-requests-create-docusign-contract | Create and send the DocuSign envelope |
Credit Line Requests (/credit-line-requests)
Endpoint Summary
| Method | Path | Description | Auth | Permission |
|---|---|---|---|---|
| GET | /credit-line-requests | Paginated list with filters and CSV export | token_admin | credit-line-requests |
| GET | /credit-line-requests/{id} | Request detail with enriched documents | token_admin | credit-line-requests |
| GET | /credit-line-requests/{id}/credit-line-history | History of credit line amounts for the company | token_admin | credit-line-requests |
| PATCH | /credit-line-requests/{id}/status | Approve (commercial) or reject a request | token_admin | credit-line-requests-manage |
| PATCH | /credit-line-requests/{id}/details | Update approved amount, days, credit line type | token_admin | credit-line-requests-manage |
| PATCH | /credit-line-requests/{id}/documents/{documentId} | Approve or reject a single document | token_admin | credit-line-requests-review-documents |
| PATCH | /credit-line-requests/{id}/documents/bulk | Bulk approve or reject all documents | token_admin | credit-line-requests-review-documents |
| PUT | /credit-line-requests/{id}/documents/{documentId}/file | Upload a file for a document slot | token_admin | credit-line-requests-manage |
| POST | /credit-line-requests/{id}/pagare/format | Upload the pagaré format for the client to sign (Mexico) | token_admin | credit-line-requests-manage |
| PATCH | /credit-line-requests/{id}/pagare/validate | Validate (approve/reject) the client's signed pagaré (Mexico) | token_admin | credit-line-requests-review-documents |
| GET | /credit-line-requests/{id}/documents/download | Download all documents as ZIP | token_admin | credit-line-requests |
| POST | /credit-line-requests/{id}/contract | Create and send DocuSign envelope | token_admin | credit-line-requests-create-docusign-contract |
| GET | /credit-line-requests/{id}/contract/signed-download | Stream signed contract PDF from S3 | token_admin | credit-line-requests |
| POST | /credit-line-requests/{id}/contract/signed-storage-sync | Re-download signed PDF from DocuSign and persist to S3 | token_admin | credit-line-requests |
| POST | /credit-line-requests/webhooks/docusign | DocuSign Connect callback (no JWT; HMAC-secured) | None | — |
GET /credit-line-requests
Returns a paginated list of credit line requests. When report=true, streams a CSV export.
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
start | number | No | Offset (default: 0) |
length | number | No | Page size (default: 25) |
sortBy | string | No | Column to sort by |
sortType | string | No | asc or desc |
status | string | No | Filter by request status |
contractStatus | string | No | Filter by contract status |
company | number | No | Filter by company ID |
ticketId | number | No | Filter by ticket ID |
startDate | string | No | Creation date range start (YYYY-MM-DD) |
endDate | string | No | Creation date range end (YYYY-MM-DD) |
localeId | any | No | Filter by locale (injected by filterLocaleV2 middleware) |
report | boolean | No | When true, streams a CSV export instead of JSON |
Response (200):
{
"draw": 25,
"recordsTotal": 120,
"recordsFiltered": 34,
"data": [
{
"id": 42,
"ticket_id": 1001,
"company_id": 55,
"company_name": "Acme Corp",
"country_code": "MX",
"assigned_to_name": "Legal Executive Name",
"requested_amount": 500000,
"requested_days": 30,
"approved_amount": null,
"approved_days": null,
"status": "pending_commercial",
"contract_status": "no_contract",
"sla_days": 3,
"created_at": "2026-04-01T10:00:00Z"
}
]
}GET /credit-line-requests/{id}
Returns a single request with all submitted documents enriched with document_name and document_type resolved from catalog_credit_line_variables via the generic_forms field map.
Response (200):
{
"data": {
"id": 42,
"company_id": 55,
"ticket_id": 1001,
"status": "approved_commercial",
"contract_status": "sent",
"docusign_envelope_id": "abc123-...",
"requested_amount": 500000,
"requested_days": 30,
"approved_amount": 300000,
"approved_days": 30,
"rejection_reason": null,
"requires_pagare": true,
"documents": [
{
"id": 10,
"document_name": "RFC Certificate",
"document_type": "file",
"value": null,
"status": "approved",
"required": true,
"rejection_reason": null
},
{
"id": 31,
"field_id": "pagare_format",
"document_type": "file",
"value": "https://s3.amazonaws.com/envia/credit-line-requests/42/pagare/...",
"status": "approved"
},
{
"id": 32,
"field_id": "pagare_signed",
"document_type": "file",
"value": "https://s3.amazonaws.com/envia/...",
"status": "approved"
}
]
}
}requires_pagare (boolean) tells the frontend whether to render the pagaré sub-flow. The pagare_format/pagare_signed documents are returned in the same documents array but are surfaced in a dedicated UI section rather than the generic document list.
PATCH /credit-line-requests/{id}/status
Advances or terminates the request lifecycle.
Payload:
{
"status": "approved_commercial",
"rejection_reason": null
}| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | approved_commercial or rejected |
rejection_reason | string | No | Required when status = rejected |
Response: 204 No Content
PATCH /credit-line-requests/{id}/details
Updates the commercial team's decisions (approved amount, term, credit type).
Payload (at least one field required):
{
"approved_amount": 300000,
"approved_days": 30,
"credit_line_type": 1
}Response: 204 No Content
PATCH /credit-line-requests/{id}/documents/{documentId}
Approves or rejects a single submitted document.
Payload:
{
"status": "rejected",
"rejection_reason": "Document is illegible"
}| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | approved or rejected |
rejection_reason | string | Conditional | Required when status = rejected |
Response: 204 No Content
PATCH /credit-line-requests/{id}/documents/bulk
Applies the same status to all documents on the request in one call.
Payload:
{
"status": "approved",
"rejection_reason": null
}Response: 204 No Content
PUT /credit-line-requests/{id}/documents/{documentId}/file
Uploads a binary file for a document slot. Accepts multipart/form-data.
Payload: file field (max 10 MB).
Response: 204 No Content
POST /credit-line-requests/{id}/pagare/format
Mexico-only sub-flow. Legal uploads the pagaré format (the unsigned promissory note) for the client to download and sign. Stores it as the pagare_format document and moves the request to pagare_sent. A system comment with signing instructions (Monterrey legal office) is added to the linked ticket.
Accepts multipart/form-data.
Payload: file field (max 10 MB; PDF/DOC/DOCX).
Preconditions (validated server-side):
- Request status is
approved_commercial - The company's country requires a pagaré (an active
credit_line_request_pagareform exists) - All required KYC/KYB documents are approved
Response (200):
{ "data": { "status": "pagare_sent" } }Errors:
| Status | When |
|---|---|
| 404 | Credit line request not found |
| 400 | Request not in approved_commercial status |
| 400 | Pagaré flow not enabled for the company's country |
| 400 | Required documents not all approved (response includes pending_documents) |
PATCH /credit-line-requests/{id}/pagare/validate
Mexico-only sub-flow. Legal validates the client's signed pagaré. The request must be in pagare_review and a pagare_signed document must exist.
Payload:
{ "status": "approved" }| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | approved or rejected |
Behavior:
approved→ markspagare_signedapproved and moves the request topagare_validated(ready to create the DocuSign contract).rejected→ deletes the signed pagaré file (S3) and its row, returns the request topagare_sentso the client re-uploads.
Response (200):
{ "data": { "status": "pagare_validated" } }Errors:
| Status | When |
|---|---|
| 404 | Credit line request not found |
| 400 | Request not in pagare_review status |
| 400 | No signed pagaré has been uploaded |
POST /credit-line-requests/{id}/contract
Validates contract preconditions and creates a DocuSign envelope from the registered template for the company's locale and person type.
Preconditions (validated server-side):
- Request status is
approved_commercialorpagare_validated - All required documents are approved
- For pagaré countries (Mexico): the signed pagaré (
pagare_signed) is approved - No existing DocuSign envelope
On success the request moves to contract_sent (and contract_status = sent).
Response: 204 No Content
Errors:
| Status | When |
|---|---|
| 400 | Request not in approved_commercial or pagare_validated status |
| 400 | Signed pagaré not yet validated (pagaré countries) |
| 409 | Required documents not all approved |
| 409 | DocuSign envelope already exists |
| 404 | No active DocuSign contract config for this locale + person type |
POST /credit-line-requests/webhooks/docusign
Receives DocuSign Connect event notifications. No JWT auth. Secured by HMAC-SHA256 via X-DocuSign-Signature-1 header.
Supports both flat envelope JSON (eSign legacy) and Connect 2.0 JSON format (restv2.1).
On a Completed envelope event:
- Looks up the request by
docusign_envelope_id - Updates
contract_statustosigned - Downloads combined PDF from DocuSign and stores in S3
- Inserts a system comment on the linked ticket (i18n-resolved in the company's language)
Response: 200 OK (empty body)
Error responses:
| Status | When |
|---|---|
| 401 | HMAC signature missing or invalid |
| 500 | DOCUSIGN_CONNECT_HMAC_SECRET not configured |
POST /credit-line-requests/{id}/contract/signed-storage-sync
Manually triggers re-download of the signed contract PDF from DocuSign and re-upload to S3. Use this when the automatic webhook PDF persistence failed.
Response: 200 OK
{ "url": "https://s3.amazonaws.com/envia/contracts/..." }DocuSign Credit Contracts (/docusign-credit-contracts)
Configuration registry that maps DocuSign Template IDs to locale + person type combinations. Used by the contract creation flow to resolve which DocuSign template to use.
Endpoint Summary
| Method | Path | Description | Auth | Permission |
|---|---|---|---|---|
| GET | /docusign-credit-contracts | Paginated list | token_admin | contract-templates |
| POST | /docusign-credit-contracts | Create new config entry | token_admin | create-contract-templates |
| GET | /docusign-credit-contracts/{id} | Get single entry | token_admin | contract-templates |
| PATCH | /docusign-credit-contracts/{id} | Update config entry | token_admin | create-contract-templates |
GET /docusign-credit-contracts
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
start | number | No | Offset (default: 0) |
length | number | No | Page size (default: 25) |
sortBy | string | No | Column to sort |
sortType | string | No | asc or desc |
localeId | number | No | Filter by locale |
personType | string | No | kyb or kyc |
isActive | number | No | 0 or 1 |
Response (200):
{
"draw": 25,
"recordsTotal": 4,
"recordsFiltered": 4,
"data": [
{
"id": 1,
"name": "Credit Line Contract MX KYB",
"description": null,
"docusign_template_id": "a1b2c3d4-...",
"locale_id": 1,
"country_code": "MX",
"country_name": "Mexico",
"person_type": "kyb",
"is_active": 1,
"created_by_name": "Admin User",
"created_at": "2026-03-01T00:00:00Z"
}
]
}POST /docusign-credit-contracts
Creates a new DocuSign template config entry.
Payload:
{
"name": "Credit Line Contract MX KYC",
"description": "Template for individual clients in Mexico",
"docusign_template_id": "d4e5f6...",
"locale_id": 1,
"person_type": "kyc",
"is_active": true
}Response (201):
{ "id": 5 }Errors:
| Status | When |
|---|---|
| 409 | Another active entry already exists for this locale + person_type |
PATCH /docusign-credit-contracts/{id}
Updates an existing config entry. Same payload as POST.
Response: 204 No Content
Client API Endpoints (queries repo)
These endpoints are served by the queries API and consumed by the client portal. They are documented here for cross-repo traceability.
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /credit-line/eligibility | Check if company is eligible to submit a credit line request | Client JWT |
| GET | /credit-line/documents | Get required document checklist for the company's locale + person type | Client JWT |
| GET | /credit-line/request/:ticket_id | Get credit line request status and documents for a given ticket | Client JWT |
| PATCH | /credit-line/documents/:document_id | Resubmit a rejected document | Client JWT |
GET /credit-line/eligibility
Response (200) — eligible:
{
"eligible": true,
"reason": null,
"last_request_id": null,
"ticket_id": null,
"criteria": null
}Response (200) — not eligible:
{
"eligible": false,
"reason": "criteria_not_met",
"last_request_id": 7,
"ticket_id": 1001,
"criteria": {
"antiquity": { "met": true, "value_days": 180, "required_days": 90 },
"delivered_guides": { "met": false, "value": 200, "required": 300 },
"used_balance": { "met": true, "value": 150000, "currency": "MXN" }
}
}Blocking reasons (not criteria): pending_commercial, approved_commercial, legal_review, active — returned directly as reason when a live request or active credit exists.
Common Error Responses
All errors follow the Boom format:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Descriptive error message"
}| Status | When |
|---|---|
| 400 | Validation failed (Joi schema) |
| 401 | Missing or invalid JWT / invalid DocuSign HMAC |
| 403 | Insufficient permissions for the action |
| 404 | Resource not found |
| 409 | Business rule conflict |
| 500 | Internal server error or missing required env var |
