Crear venta
POST /sales/ordersRegistra una venta con sus datos de cliente e ítems en la empresa asociada a la credencial.
Permiso requerido
sales.orders:write
La API registra al creador como API · nombre de la integración. No requiere configurar un vendedor en la credencial. No necesita sesión de usuario ni un token de la aplicación interna.
El contrato inicial crea únicamente borradores, sin pagos, descuentos manuales, emisión fiscal ni movimiento de inventario. El precio debe coincidir con el catálogo aplicable a moneda, cliente, canal y unidad de medida. Un precio diferente se rechaza con 403, incluso si el vendedor tiene permiso interno para modificar precios.
Reintentos y referencias externas
Envía un external_id estable por venta y reutilízalo al reintentar después de un timeout. La primera creación devuelve 201; repetir la misma referencia con la misma API key devuelve 409 con code: "external_id_conflict", sin crear ni modificar la venta existente, aunque cambie el cuerpo. La restricción también cubre solicitudes concurrentes. Otra API key puede usar la misma referencia. Si omites el campo o envías null, cada solicitud puede crear una venta nueva.
Cabeceras
| Cabecera | Valor |
|---|---|
X-Api-Key | Tu API key. |
X-Api-Secret | Tu API secret. |
Accept | application/json |
Content-Type | application/json |
X-External-Actor-Id | Opcional. Referencia del usuario en tu sistema, hasta 255 caracteres sin controles. No autentica ni concede permisos. |
Cuerpo de la solicitud
Esta referencia inicial cubre una venta en borrador, sin pagos ni emisión fiscal. Los IDs, SKU y códigos son ilustrativos: reemplázalos por valores existentes en tu empresa. is_draft: true conserva la venta como borrador.
Cabecera de la venta
| Campo | Tipo | Uso en este flujo |
|---|---|---|
origin_warehouse_id | integer | Obligatorio. Almacén de origen existente. |
issue_date | string | Obligatorio. Fecha de emisión; usa YYYY-MM-DD. |
document_code | string | Obligatorio. Código de tipo de documento existente. |
currency | string | Obligatorio. Código de moneda de tres caracteres, por ejemplo PEN. |
source | string | Opcional. Origen de la venta; solo admite api; si se omite, la API lo asigna. |
sale_channel_code | string | Obligatorio. Código existente en el catálogo de canales de venta. |
payment_term_id | integer | Obligatorio. Condición de pago existente. |
include_tax | boolean | Obligatorio. Indica si el precio incluye impuestos. |
process_inventory | boolean | Opcional. Solo se admite false; por defecto false. |
is_draft | boolean | Solo se admite true; por defecto true. No admite payments. |
external_id | string o null | Referencia opcional del sistema integrador, hasta 255 caracteres. Única por API key; repetirla devuelve 409. |
exchange_rate | number | Opcional, mayor que cero; por defecto 1. |
seller_id | integer o null | Opcional. Miembro activo de la empresa. Requiere también sales.orders:assign-seller. No modifica el creador. |
notes | string o null | Observaciones de la venta, hasta 5000 caracteres. |
Cliente
| Campo | Tipo | Uso en este flujo |
|---|---|---|
customer.name | string | Obligatorio, hasta 255 caracteres. |
customer.identity_document_type_code | string | Código de documento de identidad existente, por ejemplo RUC. Obligatorio. |
customer.tax_id | string | Número de identificación utilizado para buscar o crear el cliente. Obligatorio. |
customer.email | string o null | Correo válido, hasta 255 caracteres. |
customer.billing_address | object o null | Dirección de facturación; el ejemplo usa address. |
customer.shipping_address | object o null | Dirección de envío opcional. |
Ítems
items es un arreglo obligatorio de 1 a 200 elementos.
| Campo | Tipo | Uso en este flujo |
|---|---|---|
items[].sku | string | Obligatorio. SKU existente en el catálogo de productos de la empresa. |
items[].name | string | Obligatorio. Descripción. |
items[].qty | number | Obligatorio. Cantidad mayor que cero. |
items[].price | number | Obligatorio, mayor o igual a cero. Precio unitario; su interpretación depende de include_tax. |
items[].uom_code | string | Unidad de medida configurada para el producto. Obligatoria. |
items[].tax_exemption_code | string | Código de afectación obligatorio; por ejemplo 10 para una operación gravada en Perú. |
items[].tax_codes | string[] | Obligatorio, al menos un impuesto existente. Por ejemplo ["IGV"]. |
Los códigos de impuestos se normalizan a mayúsculas, se recortan y se eliminan duplicados. Si un ítem incluye ICBPER, también debe incluir IGV.
Ejemplo de solicitud
Guarda este JSON como venta.json. El canal DIRECT, el documento 01, la unidad NIU, el SKU y los IDs deben existir en tu empresa.
{
"origin_warehouse_id": 1,
"external_id": "integracion-venta-0001",
"issue_date": "2026-11-05",
"document_code": "01",
"currency": "PEN",
"sale_channel_code": "DIRECT",
"source": "api",
"payment_term_id": 1,
"include_tax": true,
"process_inventory": false,
"is_draft": true,
"customer": {
"name": "Empresa de ejemplo SAC",
"identity_document_type_code": "RUC",
"tax_id": "20123456789",
"email": "integraciones@example.com",
"billing_address": {
"address": "Av. Ejemplo 123, Lima"
},
"shipping_address": null
},
"items": [
{
"sku": "PRODUCTO-001",
"name": "Producto de ejemplo",
"qty": 1,
"uom_code": "NIU",
"price": 118,
"tax_exemption_code": "10",
"tax_codes": ["IGV"]
}
],
"notes": "Venta creada desde una integración"
}Con las variables de entorno de primeros pasos:
curl --request POST 'https://api.simple.pe/sales/orders' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "X-Api-Key: ${SIMPLE_API_KEY}" \
--header "X-Api-Secret: ${SIMPLE_API_SECRET}" \
--data-binary @venta.jsonRespuesta · 201 Created
La API devuelve la venta dentro de data. Este es un extracto ilustrativo, no una respuesta capturada ni el listado completo de campos:
{
"data": {
"id": 123,
"external_id": "integracion-venta-0001",
"source": "api",
"seller_id": null,
"created_by": {
"type": "api_key",
"id": 42,
"name": "Shopify",
"label": "API · Shopify",
"external_actor_id": null
},
"status": "draft",
"currency": "PEN",
"subtotal_net": "100.00",
"tax_total": "18.00",
"total": "118.00"
}
}Los importes de respuesta se serializan como cadenas. El detalle incluye cliente, ítems, seller_id (puede ser null) y created_by para identificar al creador. La respuesta pública es independiente de la utilizada por la aplicación interna.
Errores
| Código | Motivo |
|---|---|
401 | Credenciales ausentes o incorrectas. |
403 | Credencial, empresa o IP sin acceso, scope insuficiente o precio diferente al catálogo. |
409 | Ya existe una venta con ese external_id para la misma API key (external_id_conflict). |
422 | Error de validación, por ejemplo fecha ausente, vendedor inexistente/inactivo o de otra empresa, canal inexistente, ítems sin impuestos o cabecera de actor externo inválida. |
429 | Se excedió el cupo de la credencial. |
Consulta errores comunes y límites.
Alcance de esta referencia
El flujo inicial documentado es una venta en borrador. Pagos POS, anticipos, descuentos, emisión fiscal y archivos adjuntos no forman parte de este contrato. No envíes campos internos como send_to_fiscal, payments o global_discount. La API solo procesa los campos documentados.