# API Conventions

This page documents the design conventions that apply to all Dinie API endpoints. Understanding these conventions helps you predict API behavior even before consulting each endpoint's reference.

## Versioning

The major version is in the URL path: `/v3/...`

All responses include the version header:


```
X-API-Version: 2026-03-01
```

The version uses a date format (`YYYY-MM-DD`). Non-breaking changes (new fields, new endpoints, new webhook events) are introduced under a new date. Breaking changes require a new major version.

## URLs and Resources

### Path Format

URL path segments use **kebab-case**, lowercase:


```
/v3/credit-offers/{id}
/v3/credit-offers/{id}/simulations
/v3/webhooks/endpoints/{id}/secret/rotate
```

### Resource Naming

- Plural nouns for collections: `/customers`, `/credit-offers`, `/loans`
- Individual resource accessed via `/{collection}/{id}`
- Sub-resources nested under parent: `/v3/customers/{id}/kyc-attachments`
- Nesting goes at most 2 levels deep


### Actions

Non-CRUD actions use a verb suffix on the resource path:


```
POST /v3/webhooks/endpoints/{id}/secret/rotate
```

## Field Naming

### Request and Response Bodies

All field names use **snake_case**:


```json
{
  "approved_amount": 50000.00,
  "interest_rate": 3.50,
  "created_at": 1709546400
}
```

No camelCase, PascalCase, or kebab-case in JSON bodies.

### Query Parameters

Query parameters also use **snake_case**:


```
GET /v3/customers?external_id=partner123&starting_after=cust_abc123
```

### Headers

- Webhook headers: lowercase with dashes (`webhook-id`, `webhook-timestamp`, `webhook-signature`)
- OAuth headers: standard (`Authorization: Bearer ...`)
- API headers: `X-` prefix with PascalCase segments (`X-API-Version`, `X-RateLimit-Limit`)


## Date and Time

### Timestamps

All datetime fields use **Unix epoch** (integer, seconds since January 1, 1970 UTC):


```json
"created_at": 1709546400
```

In OpenAPI: `type: integer, format: int64`.

No timezone is included in the value -- Unix timestamps are inherently UTC.

### Date-Only Fields

Fields that represent a calendar date without a time component use **ISO 8601 date** (`YYYY-MM-DD`) as a string:


```json
"due_date": "2026-04-03"
```

In OpenAPI: `type: string, format: date`.

## Monetary Values

All monetary values are represented as **JSON numbers** (`number`) with two decimal places of precision:


```json
{
  "approved_amount": 50000.00,
  "monthly_payment": 2289.42,
  "iof": 450.00
}
```

### Rules

- Currency is always BRL (Brazilian Real) -- not included in the response since the platform operates exclusively in BRL
- Precision: always exactly 2 decimal places
- OpenAPI format: `type: number, format: double`


## Null Fields

Fields with no value are included in the response as `null` rather than omitted. This makes the response schema predictable regardless of state:


```json
{
  "id": "cust_abc123",
  "trading_name": null,
  "expires_at": null,
  "approved_amount": null
}
```

In OpenAPI, nullable fields use `type: ["string", "null"]` (JSON Schema 2020-12 syntax, supported in OpenAPI 3.1).

## Unknown Fields

Unknown fields in request bodies are **silently ignored** (not rejected). This allows forward compatibility when new fields are added. The OpenAPI specification does **not** set `additionalProperties: false`.

Similarly, when receiving API responses, your code should ignore fields it does not recognize -- new fields may be added without notice in minor versions.

## Common Response Fields

These fields appear on most resources:

| Field | Type | Format | Description |
|  --- | --- | --- | --- |
| `id` | string | Prefixed ID | Unique resource identifier (e.g., `cust_`, `ln_`, `co_`) |
| `status` | string | enum | Current lifecycle state (when applicable) |
| `created_at` | integer | int64 | Unix epoch (seconds) of creation |
| `updated_at` | integer | int64 | Unix epoch (seconds) of last modification (when applicable) |


### Identifiers

All IDs exposed by the API are **prefix + UUID without dashes**. The prefix indicates the resource type:

| Resource | Prefix | Example |
|  --- | --- | --- |
| Customer | `cust_` | `cust_550e8400e29b41d4a716446655440000` |
| Credit Offer | `co_` | `co_550e8400e29b41d4a716446655440000` |
| Loan | `ln_` | `ln_550e8400e29b41d4a716446655440000` |
| Simulation | `sim_` | `sim_550e8400e29b41d4a716446655440000` |
| Transaction | `tx_` | `tx_550e8400e29b41d4a716446655440000` |
| Webhook Endpoint | `we_` | `we_550e8400e29b41d4a716446655440000` |


IDs are always strings, never integers. They are immutable for the lifetime of the resource.