> For the complete documentation index, see [llms.txt](https://docs.bullcredtech.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bullcredtech.com/api-reference/apis-en/proposal-flow/post-proposals-contract.md).

# 7. Generate contract

Contract generation supports **three modes**, all compatible with the polling endpoint [`GET /proposals/{proposalId}/contract`](/api-reference/apis-en/proposal-flow/get-proposals-contract-status.md):

| Mode                     | Endpoint                                           | When to use                                                                                                                                                     |
| ------------------------ | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Hybrid (recommended)** | `POST /proposals/{proposalId}/contract`            | Waits up to 28s trying to respond synchronously; if it exceeds that, it returns `202` + tracking and continues in the background. **Default** since 2026-05-11. |
| **Explicit async**       | `POST /proposals/{proposalId}/contract/async`      | Always returns `202` immediate. Recommended for mobile/web that doesn't want to block the screen during generation.                                             |
| **Legacy async**         | `POST /proposals/{proposalId}/contract?async=true` | Semantic equivalent to `/async` — kept for compatibility. Prefer the explicit route.                                                                            |

## Hybrid mode (default)

**POST** `/proposals/{proposalId}/contract`

Generates the credit contract based on the accepted offer and starts the digital signature process via the UNICO platform.

**Behavior:**

* ✅ If generation completes in **up to \~28 seconds**: returns `201 Created` with `contract_id`, `signature_url` and complete data.
* ⏱️ If it exceeds **\~28 seconds** (typical during Celcoin slowdown windows): returns `202 Accepted` with tracking. Generation **continues in the background** and the client polls at [`GET /proposals/{proposalId}/contract`](/api-reference/apis-en/proposal-flow/get-proposals-contract-status.md).

{% hint style="info" %}
**Why the 28s limit?** The API Gateway cuts off requests at 30s (CloudFront limit). The hybrid mode returns earlier (28s) to ensure a structured response `202` instead of `504 Gateway Timeout` generic gateway error.
{% endhint %}

{% hint style="warning" %}
**Asynchronous Processing — critical step**

Upon receiving `202`, **the contract has not yet been generated**. The client MUST poll at [`GET /proposals/{proposalId}/contract`](/api-reference/apis-en/proposal-flow/get-proposals-contract-status.md) until the status changes (recommended: 2s interval between polls). Webhook is also supported.
{% endhint %}

## Explicit async mode

**POST** `/proposals/{proposalId}/contract/async`

Always returns `202 Accepted` immediate. Equivalent to `?async=true`, but with a semantic URL.

Use when the client wants to **release the UI** as soon as the request is accepted, without waiting for any synchronous moment.

## URL Parameters

| Parameter    | Type          | Description |
| ------------ | ------------- | ----------- |
| `proposalId` | string (UUID) | Proposal ID |

## Query Parameters (legacy mode)

| Parameter | Type    | Description                                                                                                |
| --------- | ------- | ---------------------------------------------------------------------------------------------------------- |
| `async`   | boolean | If `true`, it is equivalent to `POST /contract/async`. Kept for compatibility — prefer the explicit route. |

## Request Body (Optional)

| Field                    | Type         | Required | Description                                |
| ------------------------ | ------------ | :------: | ------------------------------------------ |
| `signature_redirect_url` | string (URL) |    No    | URL to redirect the customer after signing |

## Request Example

```json
{
  "signature_redirect_url": "https://seu-sistema.com/assinatura/concluida"
}
```

If not provided, the customer will be redirected to UNICO's default page.

## Success Response (201 Created)

```json
{
  "message": "Contract generated successfully",
  "contract_id": "9f195264-b1f5-415f-97ea-8e7a51e04238",
  "status": "CONTRACT_GENERATED",
  "principal_amount": "25153.66",
  "interest_rate": "4.99",
  "installments": 18,
  "total_amount": "41903.28",
  "installment_amount": "2327.96",
  "first_due_date": "2025-12-20",
  "has_original_document": true,
  "user_redirect_url": "https://cadastro.uat.unico.app/process/1b8fc7d3-4012-4fb4-84cd-c0025d9b13d0",
  "unico_process_id": "1b8fc7d3-4012-4fb4-84cd-c0025d9b13d0",
  "digital_signature": {
    "signature_id": "ba0ded34-daf1-4433-8320-4e7e9fd19503",
    "unico_process_id": "1b8fc7d3-4012-4fb4-84cd-c0025d9b13d0",
    "user_redirect_url": "https://cadastro.uat.unico.app/process/1b8fc7d3-4012-4fb4-84cd-c0025d9b13d0",
    "status": "PENDING",
    "expires_at": "2025-10-15T02:00:00.000Z"
  },
  "contract_details": {
    "principal_amount": "25153.66",
    "interest_rate": "4.99",
    "installments": 18,
    "total_amount": "41903.28",
    "installment_amount": "2327.96",
    "first_due_date": "2025-12-20",
    "disbursement_date": "2025-10-14"
  }
}
```

### Identifiers

| Field               | Type          | Description                                        |
| ------------------- | ------------- | -------------------------------------------------- |
| `contract_id`       | string (UUID) | Unique ID of the generated contract                |
| `unico_process_id`  | string (UUID) | UNICO signing process ID                           |
| `user_redirect_url` | string (URL)  | **URL to redirect the customer** to sign digitally |

### Digital Signature (`digital_signature`)

| Field               | Type              | Description               |
| ------------------- | ----------------- | ------------------------- |
| `signature_id`      | string (UUID)     | Unique signature ID       |
| `status`            | string            | Current status: `PENDING` |
| `user_redirect_url` | string (URL)      | Signature URL             |
| `expires_at`        | string (ISO 8601) | Signature deadline        |

### Contract Details (`contract_details`)

| Field                | Type   | Description                |
| -------------------- | ------ | -------------------------- |
| `principal_amount`   | string | Net loan amount            |
| `interest_rate`      | string | Monthly interest rate (%)  |
| `installments`       | number | Number of installments     |
| `total_amount`       | string | Total amount to be paid    |
| `installment_amount` | string | Amount of each installment |
| `first_due_date`     | string | Date of the first due date |
| `disbursement_date`  | string | Expected disbursement date |

## Asynchronous Response (202 Accepted)

Returned in **two scenarios**:

1. **Hybrid mode — synchronous timeout exceeded (\~28s).** The generation did not finish within the HTTP request time budget and was moved to the background.
2. **Explicit async mode (`POST /contract/async`) or legacy (`?async=true`).** Always `202` immediate.

**In both cases:** the contract is being generated **in the background**. The client MUST poll at [`GET /proposals/{proposalId}/contract`](/api-reference/apis-en/proposal-flow/get-proposals-contract-status.md) (full URL in the field `status_url`) or wait for the webhook `CONTRACT_GENERATED`.

```json
{
  "async_processing": true,
  "message": "Synchronous timeout exceeded — contract generation continues in the background. Check GET /contract/status for the result.",
  "proposal_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "CONTRACT_GENERATION_IN_PROGRESS",
  "processing_started_at": "2025-12-01T14:30:00.000Z",
  "status_url": "/proposals/a1b2c3d4-e5f6-7890-abcd-ef1234567890/contract/status"
}
```

| Field                   | Meaning                                                                                                                    |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `async_processing`      | Always `true` in this response.                                                                                            |
| `message`               | Human-readable text. In hybrid mode, indicates that the synchronous limit was exceeded.                                    |
| `proposal_id`           | Proposal identifier — use to correlate with webhooks/logs.                                                                 |
| `status`                | Always `CONTRACT_GENERATION_IN_PROGRESS` while the background runs.                                                        |
| `processing_started_at` | ISO 8601 timestamp (UTC) of when the background started.                                                                   |
| `status_url`            | Relative URL for polling — points to `GET /proposals/{id}/contract/status` (same shape as `GET /proposals/{id}/contract`). |

**Recommended polling pattern:** 2-second interval; abandon after \~3 minutes (background has an internal 3-minute watchdog). Status `200 OK` indicates that the result is ready; `202` continues in progress.

## Possible Errors

| Code | Error Code                        | Message                                                            |
| ---- | --------------------------------- | ------------------------------------------------------------------ |
| 404  | -                                 | Proposal not found                                                 |
| 409  | `SIGNED_CONTRACT_EXISTS`          | There is already a signed contract for this proposal               |
| 409  | `CONTRACT_GENERATION_IN_PROGRESS` | Contract generation is already in progress                         |
| 409  | `CONTRACT_ALREADY_GENERATED`      | Contract has already been generated                                |
| 409  | `PROPOSAL_FINALIZED`              | Proposal already finalized                                         |
| 409  | `CONTRACT_ACTIVE`                 | There is already an active contract with a valid digital signature |

## Digital Signature Flow

1. **Redirect Client**: Use the URL `user_redirect_url` to redirect the customer
2. **UNICO Process**: Customer undergoes identity verification (selfie + document)
3. **Signature**: Customer digitally signs the contract
4. **Webhook**: System receives completion notification
5. **Check Status**: Use [GET /proposals/{id}/contract/status](/api-reference/apis-en/proposal-flow/get-proposals-contract-status.md) to check

## Signature Deadline

| Scenario                           | Deadline                          |
| ---------------------------------- | --------------------------------- |
| Contract generated **before 9 PM** | Until 9 PM on the **next day**    |
| Contract generated **after 9 PM**  | Until 9 PM of **2 business days** |

## Possible Signature Statuses

| Status        | Description                             |
| ------------- | --------------------------------------- |
| `PENDING`     | Waiting for customer signature          |
| `IN_PROGRESS` | Customer started the process in UNICO   |
| `SIGNED`      | Contract signed successfully            |
| `EXPIRED`     | Signature deadline expired              |
| `REJECTED`    | Signature rejected (validation failure) |

## Notes

* The contract is generated in PDF format and stored securely
* The signature URL expires according to the field `expires_at`
* After successful signing, the status changes to `SIGNED`
* Disbursement occurs automatically after signing (next business day)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.bullcredtech.com/api-reference/apis-en/proposal-flow/post-proposals-contract.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
