Create order
Creates and submits an order in a single call. The submission re-prices the selection server-side (client-sent prices are never trusted), validates the acceptance you collected from the insured person, creates the premium charge and returns the order in awaiting_payment, together with the Pix artifact the insured person must pay.
The products[] list is the same as the quote's — quote and order use the same selection grammar, plus a per-product acceptance block. The quote is indicative: the submission re-prices against the configuration in force and the submit price is the one that counts.
QI Tech neither renders a proposal document nor hosts a signature screen in this version. You run the acceptance ceremony in your own flow and attest the outcome in each product's acceptance field. There is no acceptance_url.
ticket) only in this versionThe product states in contract_instrument_type whether it is sold as a ticket (ticket) or as a policy (policy). A ticket dispenses with the proposal — the contract is formed by the act of purchase, which is exactly what makes your attested acceptance sufficient. policy products are not sellable yet and are refused with ORD000033. The field is echoed on the quote, so you learn the instrument before collecting acceptance.
Request
{
"request_control_key": "5e2b3f60-7c4b-4c8e-9f1a-6d2e8b4a7c90",
"products": [
{
"product_key": "9d1f8c7a-3b21-4e60-8a2f-1c5d7e9b0a44",
"commission_data": {
"commission_type": "percentage_of_gross_premium",
"value": 0.1000
},
"term": {
"start_date": "2026-07-16",
"end_date": "2027-07-15"
},
"services": [
{
"service_key": "0a3c5e7f-2b4d-4a6c-8e0f-1a3b5c7d9e2f",
"insured_amount_basis": "monetary_amount",
"insured_amount": 50000.00
}
],
"risk_object": {
"type": "credit_operation",
"insurable_value": 50000.00,
"attributes": {
"installment_amount": 1050.00,
"number_of_installments": 48
}
},
"acceptance": {
"acceptance_method": "click_wrap",
"accepted_at": "2026-07-16T13:58:04Z",
"ip_address": "200.150.10.24",
"document_number_hash": "f7c3bc1d808e04732adf679965ccc34ca7ae3441ef0d5e6ba2c1d0f0d5f1e2a3",
"terms": {
"version": "2026-05-v3",
"hash": "9b74c9897bac770ffc029102a200c5de"
},
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X)",
"evidence_reference": "ceremony-8842197"
}
}
],
"customer": {
"document_number": "96969879003",
"name": "Maria Souza",
"email": "maria@example.com",
"phone_number": "+5511999990000",
"date_of_birth": "1987-03-22",
"occupation_code": "211205",
"address": {
"street": "Avenida Paulista",
"number": "1000",
"complement": "Conjunto 42",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP",
"postal_code": "01310100"
}
},
"payment_data": {
"payment_method": "pix_automatic",
"installment_count": 12
}
}
Request attributes
| Field | Type | Required | Description |
|---|---|---|---|
request_control_key | string (UUID) | optional | A control key defined by you. See Duplicate control — it is not a retry handle. |
products | array | required | The product selection, 1 to 20 items, in the same format as the quote plus the acceptance block. |
customer | object | required | The buyer/insured person of the order (one per order). |
payment_data | object | required | Premium payment method. |
Object in products[]
| Field | Type | Required | Description |
|---|---|---|---|
product_key | string | required | Product key in the catalog. Must not repeat within the same order. |
commission_data | object | optional | The desired commission form for the product. If omitted, the product's default rate (default_rate) applies. See below. |
term | object | required | Product term, in absolute dates: { "start_date": "YYYY-MM-DD", "end_date": "YYYY-MM-DD" }. There is no duration-based form and no default term at the order level. end_date must be later than start_date. |
services | array | optional | Selected coverages. If omitted, the product's default configuration applies. Same format as the quote. |
risk_object | object | required | The product's risk object (type, insurable_value, attributes). insurable_value is required for type credit_operation and vehicle. A product whose subject is the person itself states that positively as {"type": "person"} — the block is never omitted. |
acceptance | object | required | The insured person's acceptance for this product. See below. |
commission_data object
| Field | Type | Required | Description |
|---|---|---|---|
commission_type | string | required | One of three mutually exclusive forms: percentage_of_gross_premium (rate over the gross premium), monetary_amount (fixed commission in BRL) or total_gross_premium_amount (desired final price to the customer). |
value | number | required | The value of the chosen form: a rate with 4 decimals (e.g. 0.1000), an amount in BRL (e.g. 61.73) or a total price (e.g. 650.00). |
The effective commission is always validated against the product's band (commission_bounds). A value outside the band rejects the line at pricing: the order is born rejected, with OUT_OF_BOUNDS_COMMISSION in decline_reasons. An unknown commission_type or a mistyped value is a 400.
acceptance object
Acceptance is attested per product, never inherited from a sibling: each OrderProduct becomes exactly one policy, and the evidence has to survive next to the contract it justifies. When a single ceremony covered several products, repeat the block on each item.
| Field | Type | Required | Description |
|---|---|---|---|
acceptance_method | string | required | How acceptance was collected: click_wrap, checkbox, otp_sms, otp_email or voice. |
accepted_at | string | required | Acceptance timestamp, RFC 3339 (e.g. 2026-07-16T13:58:04Z). It must fall within the last 24 hours and must not be in the future beyond 5 minutes of clock skew — otherwise ORD000027. |
ip_address | string | required | The IP address (v4 or v6) the acceptance was given from. |
document_number_hash | string | required | SHA-256 (hex, 64 characters) of customer.document_number, unsalted. It is recomputed and checked server-side: a mismatch is ORD000026. |
terms | object | required | Identification of the accepted terms: { "version", "hash" }. |
user_agent | string | optional | User agent of the insured person's device (up to 512 characters). |
evidence_reference | string | optional | Reference to the evidence in your own system (up to 128 characters). |
document_number_hash is unsalted SHA-256 over a CPF — the space is exhaustively searchable. The choice is deliberate, so that any holder of the document number can re-verify the binding. Do not treat it as pseudonymised data.
customer object
The object is flat — there is no data wrapper. Unlike the quotation, where everything is optional, here the buyer is the insured of record and also the payer of the charge — which is why most fields become required.
| Field | Type | Required | Description |
|---|---|---|---|
document_number | string | required | The insured person's CPF (11 digits) or CNPJ (14 digits), digits only. |
name | string | required | Full name. |
email | string | required | The insured person's e-mail. |
phone_number | string | required | Phone number, 10 to 15 digits, optionally prefixed with +. |
date_of_birth | string | required | The insured person's date of birth, as YYYY-MM-DD. The age read by the pricing and eligibility rules is derived from it at quotation time — do not send an age. |
occupation_code | string | optional | Occupation code (CBO). If the product prices or evaluates eligibility by occupation, omitting the code rejects the line — the order is born rejected with the reason in decline_reasons, not 400. Check the product in the catalogue to find out whether it reads this field. |
address | object | required | The insured person's address. |
customer.address object
| Field | Type | Required | Description |
|---|---|---|---|
street | string | required | Street. |
number | string | required | Number. |
complement | string | optional | Complement. |
neighborhood | string | required | Neighborhood. |
city | string | required | City. |
state | string | required | State. |
postal_code | string | required | Postal code, 8 digits, no separators. |
payment_data object
| Field | Type | Required | Description |
|---|---|---|---|
payment_method | string | required | Premium payment method. The only value accepted in this version is pix_automatic (Pix Automático). |
installment_count | integer | required | Number of premium installments, from 1 to 24. |
Duplicate control
request_control_key is a uniqueness assertion, not a retry handle. Any second use of the same pair (your integration, request_control_key) answers 409 / ORD000011 — an identical body included. Nothing compares bodies.
A submit that times out may still have committed. Repeating the call with the same request_control_key answers 409 and does not return the order. The recovery path is GET /v1/insurance/order?request_control_key={your_key}. Retrying with a new key sells the same thing twice.
Response
POST always answers 201A business decline is a created resource, not a failed call: the order is born with status: "rejected" and its reasons in decline_reasons, still as a 201. Branch on status, never on the HTTP class. The error envelope is reserved for calls that never reached a decision.
Order created (awaiting_payment)
{
"order_key": "5e2b3f60-7c4b-4c8e-9f1a-6d2e8b4a7c90",
"status": "awaiting_payment",
"distribution_type": "direct",
"expires_at": "2026-07-23T13:58:04Z",
"quote_data": {
"total_order_amount": 617.28,
"products": [
{
"order_product_key": "7f3a9c2e-0b5d-4e8a-a1c6-9d4b2e7f0a53",
"product_key": "9d1f8c7a-3b21-4e60-8a2f-1c5d7e9b0a44",
"product_category": "insurance",
"insurance_class": {
"name": "credit_life",
"class_number": "0977",
"group_number": "09"
},
"regulator_registration": "15414.900388/2015-21",
"contract_instrument_type": "ticket",
"gross_premium_amount": 617.28,
"iof_amount": 2.35,
"net_premium_amount": 614.93,
"term": {
"start_date": "2026-07-16",
"end_date": "2027-07-15"
},
"risk_object": {
"type": "credit_operation",
"insurable_value": 50000.00,
"attributes": {
"installment_amount": 1050.00,
"number_of_installments": 48
}
},
"services": [
{
"service_key": "0a3c5e7f-2b4d-4a6c-8e0f-1a3b5c7d9e2f",
"service_type": {
"code": "credit_life",
"name": "Prestamista (Credit Life)"
},
"service_category": "insurance",
"regulator_registration": null,
"gross_premium_amount": 617.28,
"insured_amount": 50000.00,
"unit_amount": null,
"unit_count": null,
"deductible_data": {
"deductible_type": "monetary_amount",
"value": 1500.00
},
"waiting_period_days": 30,
"service_attributes": {},
"term": {
"start_date": "2026-07-16",
"end_date": "2027-07-15"
}
}
]
}
]
},
"payment_data": {
"payment_method": "pix_automatic",
"installment_count": 12,
"installment_amount": 51.44,
"first_installment_amount": 51.44,
"first_due_date": "2026-07-23",
"payment_artifact": {
"type": "pix_automatic",
"qr_code_payload": "https://pix.example.qitech.app/r/9f2c1b0e",
"qr_code_key": "9f2c1b0e-5d47-4a11-9c3e-0b8a7d61f402"
}
},
"customer_document_number": "96969879003"
}
| Field | Type | Description |
|---|---|---|
order_key | string | Unique key of the order. |
status | string | awaiting_payment on a created order. See the lifecycle. |
distribution_type | string | Distribution model of the sale. Always direct today. |
expires_at | string | Deadline for the first installment payment: 7 days from submission. Past the deadline the order expires. |
quote_data | object | What was sold and frozen at submission: total_order_amount and the products with their coverages. It is the same block, in the same shape, returned by the order detail read. |
quote_data.products[].order_product_key | string | Key of the product within the order. It is the correlation key with the policy generated at emission. |
payment_data | object | The charge created for the order. See below. |
customer_document_number | string | The insured person's document number. |
payment_data object (response)
| Field | Type | Description |
|---|---|---|
payment_method | string | The frozen payment method — pix_automatic. |
installment_count | integer | Number of installments. |
installment_amount | number | Amount of each installment. |
first_installment_amount | number | Amount of the first installment — it absorbs the rounding residue, so that first_installment_amount + (installment_count - 1) × installment_amount reconciles exactly with total_order_amount. |
first_due_date | string | Due date of the first installment (YYYY-MM-DD). |
payment_artifact | object | The Pix artifact to hand to the insured person: type, qr_code_payload (the Pix URL, not the EMV copy-and-paste string) and qr_code_key. Returned only while the order is awaiting_payment — on an emitted or terminal order the QR is spent and is not re-exposed. |
Order rejected (rejected)
When pricing refuses any line, the order is born rejected. The submission is all-or-nothing: one refused line refuses the whole order, no charge is created and no product row is persisted. The resource still exists and is readable by its order_key.
{
"order_key": "b41d90a7-8c22-4f3e-9a10-2d6e4b7c5f81",
"status": "rejected",
"decline_reasons": [
{
"product_key": "9d1f8c7a-3b21-4e60-8a2f-1c5d7e9b0a44",
"code": "INELIGIBLE",
"detail": "age_at_maturity 76 exceeds the maximum 75 for coverage credit_life"
}
]
}
| Field | Type | Description |
|---|---|---|
order_key | string | Key of the rejected order. |
status | string | Always rejected on this branch. |
decline_reasons | array | A flat list of { product_key, code, detail }, one entry per underlying failure — two coverages of one product breaching their option spaces produce two entries under the same code. The codes are the same as the quote's. product_key may be null for a reason not attributable to a specific product. |
A rejected order carries no quote_data and no payment_data: nothing was sold and there is nothing to pay.
Possible errors
Every error (non-2xx) returns the standard body { "title", "description", "translation", "code" } — handle only the code field programmatically. A business decline does not arrive here: it is the 201 with status: rejected described above.
| Status | Code | Description |
|---|---|---|
400 | QIT000001 | Malformed request (invalid schema) — including a customer.date_of_birth outside the calendar or in the future. |
401 / 403 | — | Authentication or authorization failure. |
409 | ORD000011 | request_control_key already used by your integration. Recover the order with GET /v1/insurance/order?request_control_key=. |
422 | ORD000020 | Risk object missing, or missing insurable_value when its type requires one (credit_operation/vehicle). |
422 | ORD000021 | Product without term. |
422 | ORD000022 | term.end_date earlier than or equal to term.start_date. |
422 | ORD000023 | product_key repeated within the same order. |
422 | ORD000024 | Inactive integration — it cannot transact. |
422 | ORD000025 | Product without the acceptance block. |
422 | ORD000026 | acceptance.document_number_hash does not match the order's customer.document_number. |
422 | ORD000027 | acceptance.accepted_at is invalid, in the future, or outside the 24-hour window. |
422 | ORD000028 | Your integration has no payment configuration and cannot be charged. Contact the Integration team. |
422 | ORD000029 | The requested payment method is not enabled for your integration. |
422 | ORD000032 | The order mixes different contract instruments — a ticket and a policy cannot be sold in the same order. |
422 | ORD000033 | The product's contract instrument is not available for sale (ticket only in this version). |
502 / 504 | ORD000031 | Failure in a synchronous integration of the submission (charge). No order was created. |
503 | ORD000030 | Pricing engine unavailable — sales are paused. Retry the call. |
502 / 504 / 503Repeating the submit requires the same request_control_key — or none at all. A new key creates a second order for the same sale.