Integración · Tienda y ERP

Documentación API

Contrato técnico para conectar Prestashop u otra tienda con Prodatos. Un pedido pagado puede convertirse en factura electrónica (inventario al enviar + DIAN) o en entrega (inventario, sin DIAN). No use la misma referencia externa para ambos.

Entornos y autenticación

Cada empresa genera su clave en el ERP: Configuraciones → API de tienda. La clave se muestra una sola vez.

Authorization: Bearer pk_live_xxxxxxxx_…
Llame al API desde el backend de la tienda (módulo Prestashop, webhook PHP, etc.). Nunca exponga la clave en JavaScript del navegador.

Las rutas canónicas no llevan index.php.

EntornoURL base
Evaluación (sandbox) https://prodatossas.com/desarrollo2/api/v1
Producción (clientes pagos) https://prodatossas.com/produccion/api/v1
Para facturar o entregar en producción hay que cambiar desarrollo2 por produccion. La API key no cruza de sandbox a producción: cada instancia genera la suya.

Lab local (opcional): http://localhost/repos/desarrollo2/api/v1.

Fallback si Apache no reescribe: .../api/v1/index.php/salud.

Cuándo usar facturas vs entregas

Un mismo pedido de tienda debe ir a uno u otro, nunca a los dos con la misma referencia_externa.

Salud

GET /salud

No requiere autenticación. Comprueba que el servicio responde.

Respuesta 200

{
  "ok": true,
  "servicio": "api_tienda",
  "version": "1"
}

Productos

GET /productos

Catálogo para mapear el SKU de la tienda al codigo o plu del ERP. Query: q, page, per_page (máximo 100).

Respuesta 200

{
  "ok": true,
  "page": 1,
  "per_page": 50,
  "total": 1,
  "productos": [
    {
      "product_id": 12,
      "codigo": "ABC-01",
      "plu": "ABC-01",
      "nombre": "Camiseta",
      "descripcion": "Camiseta algodón",
      "marca": "Marca",
      "precio_con_iva": 45000,
      "iva": 19,
      "cantidad": 8,
      "activo": "A"
    }
  ]
}

GET /productos/{codigo}

Detalle de un producto y existencias (bodega de la API key si está configurada).

Respuesta 200

{
  "ok": true,
  "producto": {
    "product_id": 12,
    "codigo": "ABC-01",
    "plu": "ABC-01",
    "nombre": "Camiseta",
    "descripcion": "Camiseta algodón",
    "marca": "Marca",
    "precio_con_iva": 45000,
    "iva": 19,
    "cantidad": 8,
    "activo": "A"
  }
}

Respuesta 404

{
  "ok": false,
  "error": "Producto no encontrado."
}

Clientes

POST /clientes

Alta o actualización por numero_documento. Si omite el documento, se usa consumidor final 222222222222. Para facturas electrónicas prefiera enviar el cliente completo en el body de POST /facturas.

Body

{
  "numero_documento": "123456789",
  "razon_social": "Ana Pérez",
  "email": "ana@correo.com",
  "telefono": "3001234567",
  "direccion": "Cra 1 #2-3",
  "departamento": "11",
  "municipio": "11001"
}

Respuesta 201 (creado) o 200 (actualizado)

{
  "ok": true,
  "numero_documento": "123456789",
  "razon_social": "ANA PÉREZ",
  "creado": true,
  "actualizado": false
}

Facturas electrónicas

Alias: las mismas rutas existen bajo /invoices.

El cliente fiscal es obligatorio (documento, razón social, email, dirección, teléfono, municipio). El inventario no se descuenta al crear el borrador; se descuenta al intentar DIAN.

POST /facturas

Body

{
  "referencia_externa": "PS-12345",
  "medio_pago": "transferencia",
  "nota": "Pedido Prestashop #12345",
  "cliente": {
    "numero_documento": "123456789",
    "razon_social": "Ana Pérez",
    "email": "ana@correo.com",
    "telefono": "3001234567",
    "direccion": "Cra 1 #2-3",
    "departamento": "11",
    "municipio": "11001",
    "tercero": "3"
  },
  "lineas": [
    { "codigo": "ABC-01", "cantidad": 2, "precio_con_iva": 45000 }
  ]
}

Respuesta 201 (éxito DIAN)

{
  "ok": true,
  "idempotente": false,
  "prefijo_factura": "SETT",
  "numero_factura": "990000123",
  "estado": "ENVIADO_DIAN",
  "tipo": "API_TIENDA_FE",
  "cufe": "a1b2c3d4e5f6…",
  "medio_pago": "transferencia",
  "referencia_externa": "PS-12345",
  "numero_documento_cliente": "123456789",
  "valor_sin_iva": 75630.25,
  "valor_con_iva": 90000,
  "iva": 14369.75,
  "nota": "Pedido Prestashop #12345",
  "lineas": [
    {
      "product_id": 12,
      "codigo": "ABC-01",
      "nombre": "Camiseta",
      "cantidad": 2,
      "precio_unitario_con_iva": 45000,
      "precio_con_iva": 90000,
      "precio_sin_iva": 75630.25,
      "iva": 14369.75
    }
  ]
}

Respuesta 202 (en proceso DIAN)

{
  "ok": true,
  "prefijo_factura": "SETT",
  "numero_factura": "990000123",
  "estado": "EN_PROCESO_DIAN",
  "cufe": "a1b2c3d4e5f6…",
  "referencia_externa": "PS-12345"
}

Respuesta 502 (DIAN falló después de reservar consecutivo)

{
  "ok": false,
  "error": "Timeout al contactar Apidian. El consecutivo SETT-990000123 quedo reservado. Reintente este mismo documento; no envie otra factura.",
  "referencia_externa": "PS-12345",
  "identidad_reservada": true,
  "prefijo_factura": "SETT",
  "numero_factura": "990000123",
  "reintentar": "/facturas/SETT/990000123/reintentar"
}

Respuesta 422 (validación)

{
  "ok": false,
  "error": "cliente.email valido es obligatorio para factura electronica."
}

GET /facturas/{prefijo}/{numero}

Alternativa: GET /facturas?referencia_externa=PS-12345.

Respuesta 200

{
  "ok": true,
  "prefijo_factura": "SETT",
  "numero_factura": "990000123",
  "estado": "ENVIADO_DIAN",
  "cufe": "a1b2c3d4e5f6…",
  "referencia_externa": "PS-12345",
  "valor_con_iva": 90000,
  "lineas": []
}

POST /facturas/{prefijo}/{numero}/reintentar

Reenvía el mismo par prefijo/número. No crea otra factura ni vuelve a restar inventario.

Body

{}

Respuesta 200

{
  "ok": true,
  "prefijo_factura": "SETT",
  "numero_factura": "990000123",
  "estado": "ENVIADO_DIAN",
  "cufe": "a1b2c3d4e5f6…",
  "referencia_externa": "PS-12345"
}

Entregas

POST /entregas

Crea la venta: documento ENTR, estado POS, visible en Entregas, con descuento de inventario. referencia_externa debe ser el id del pedido en la tienda (idempotente: reenviar el mismo id no duplica).

precio_con_iva es el precio unitario con IVA. Si se omite, se usa el precio de venta del ERP.

Body

{
  "referencia_externa": "PS-12345",
  "medio_pago": "transferencia",
  "nota": "Pedido Prestashop #12345",
  "cliente": {
    "numero_documento": "123456789",
    "razon_social": "Ana Pérez",
    "email": "ana@correo.com",
    "telefono": "3001234567",
    "direccion": "Cra 1 #2-3"
  },
  "lineas": [
    { "codigo": "ABC-01", "cantidad": 2, "precio_con_iva": 45000 }
  ]
}

Respuesta 201 (o 200 si ya existía)

{
  "ok": true,
  "idempotente": false,
  "prefijo_factura": "ENTR",
  "numero_factura": "15",
  "estado": "POS",
  "tipo": "API_TIENDA",
  "medio_pago": "transferencia",
  "referencia_externa": "PS-12345",
  "numero_documento_cliente": "123456789",
  "valor_sin_iva": 75630.25,
  "valor_con_iva": 90000,
  "iva": 14369.75,
  "nota": "Pedido Prestashop #12345",
  "lineas": [
    {
      "product_id": 12,
      "codigo": "ABC-01",
      "nombre": "Camiseta",
      "cantidad": 2,
      "precio_unitario_con_iva": 45000,
      "precio_con_iva": 90000,
      "precio_sin_iva": 75630.25,
      "iva": 14369.75
    }
  ]
}

Respuesta 409 (stock)

{
  "ok": false,
  "error": "Stock insuficiente.",
  "stock": [
    { "codigo": "ABC-01", "solicitado": 2, "disponible": 0 }
  ]
}

GET /entregas/{prefijo}/{numero}

Consulta una entrega. Alternativa: GET /entregas?referencia_externa=PS-12345.

Respuesta 200

{
  "ok": true,
  "idempotente": false,
  "prefijo_factura": "ENTR",
  "numero_factura": "15",
  "estado": "POS",
  "referencia_externa": "PS-12345",
  "valor_con_iva": 90000,
  "lineas": []
}

POST /entregas/{prefijo}/{numero}/anular

Anula la entrega y reintegra el inventario. Útil si el pedido se cancela en la tienda.

Body

{}

Respuesta 200

{
  "ok": true,
  "prefijo_factura": "ENTR",
  "numero_factura": "15",
  "estado": "ANULADA",
  "referencia_externa": "PS-12345",
  "ya_anulada": false
}

Errores

401

{ "ok": false, "error": "API key invalida o revocada." }

409 stock

{ "ok": false, "error": "Stock insuficiente.", "stock": [] }

Cómo conectar una tienda

  1. En el ERP, iguale los SKU de la tienda con codigo o plu de productos. Use GET /productos?q= para verificar.
  2. Genere la API key en Configuraciones y guárdela en el módulo o en variables de entorno de la tienda.
  3. Cuando el pedido quede pagado, elija un flujo:
    • Factura electrónica: POST /facturas con los mismos datos y cliente fiscal completo.
    • Solo inventario: POST /entregas con referencia_externa = id del pedido.
  4. No reutilice la misma referencia_externa en factura y entrega.
  5. Si una factura reservó consecutivo y DIAN falló: POST /facturas/{prefijo}/{numero}/reintentar.
  6. Si una entrega se cancela: POST /entregas/ENTR/{numero}/anular.

Ejemplo cURL (evaluación):

curl -X POST "https://prodatossas.com/desarrollo2/api/v1/facturas" \
  -H "Authorization: Bearer pk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"referencia_externa":"PS-1","cliente":{"numero_documento":"123456789","razon_social":"Ana Pérez","email":"ana@correo.com","telefono":"3001234567","direccion":"Cra 1 #2-3","municipio":"11001"},"lineas":[{"codigo":"ABC-01","cantidad":1}]}'

El mismo llamado en producción:

curl -X POST "https://prodatossas.com/produccion/api/v1/facturas" \
  -H "Authorization: Bearer pk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"referencia_externa":"PS-1","cliente":{"numero_documento":"123456789","razon_social":"Ana Pérez","email":"ana@correo.com","telefono":"3001234567","direccion":"Cra 1 #2-3","municipio":"11001"},"lineas":[{"codigo":"ABC-01","cantidad":1}]}'