DocsReferencia de la APIVentasObtener una ventaObtener una ventaPermiso requerido: sales:read.GET /public/v1/sales/{id}Permiso sales:read · VentasCopiar páginaPregúntale a la IAParámetrosParámetros de rutaNombreTipoRequeridoDescripciónidstring (uuid)Sí—Ejemplo de peticióncurlNode.jsPythonPHPTerminalcurl "https://api.posdata.so/public/v1/sales/3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d" \ -H "Authorization: Bearer $POSDATA_API_KEY"JavaScriptconst res = await fetch('https://api.posdata.so/public/v1/sales/3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d', { headers: { Authorization: `Bearer ${process.env.POSDATA_API_KEY}`, }, }); const data = await res.json(); if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message} (${data.error.request_id})`);Pythonimport os import requests res = requests.get( "https://api.posdata.so/public/v1/sales/3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", headers={ "Authorization": f"Bearer {os.environ['POSDATA_API_KEY']}", }, timeout=30, ) data = res.json() if not res.ok: raise RuntimeError(f"{data['error']['code']}: {data['error']['message']} ({data['error']['request_id']})")PHP<?php $ch = curl_init('https://api.posdata.so/public/v1/sales/3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('POSDATA_API_KEY'), ], ]); $data = json_decode(curl_exec($ch), true); if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) { throw new RuntimeException("{$data['error']['code']}: {$data['error']['message']} ({$data['error']['request_id']})"); }Respuesta200 OK: un objeto Sale.CampoTipoRequeridoDescripciónobject"sale"Sí—idstring (uuid)Sí—statusstringSíEstado tal como lo registró el POS (completed, cancelled, open, pending…).document_kindstringSíDocumento que pidió el POS al cobrar. Valores: pos, invoice.payment_methodstringSíMedio de pago tal como lo registró el POS (CASH, CARD, NEQUI…).customer_idstring (uuid) | nullSí—cash_session_idstring (uuid) | nullSí—subtotalintegerSíSuma de las líneas, impuestos incluidos.discountintegerSíPesos colombianos (COP), entero sin decimales.discount_percentnumberSí—taxintegerSíParte del total que es impuesto.tip_amountintegerSíPropina. Nunca es base gravable.totalintegerSísubtotal - discount + tip_amount.tax_breakdownarreglo de TaxBreakdownEntry | nullSí—notesstring | nullSí—table_labelstring | nullSí—itemsarreglo de SaleItemSí—invoicesarreglo de InvoiceSummarySí—occurred_atstring (date-time)SíCuando se registró la venta en la caja (reloj de la caja). En ventas sincronizadas antes del 28-sep-2026 es la hora de llegada.created_atstring (date-time)SíCuando la venta llegó al servidor (una caja sin conexión la sube después).updated_atstring (date-time)Sí—Ejemplo de respuesta (valores ilustrativos){ "object": "sale", "id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "status": "texto", "document_kind": "pos", "payment_method": "texto", "customer_id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "cash_session_id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "subtotal": 25900, "discount": 1, "discount_percent": 19, "tax": 1, "tip_amount": 25900, "total": 25900, "tax_breakdown": [ { "code": "texto", "rate": null, "per_unit": null, "base": 1, "amount": 25900 } ], "notes": "texto", "table_label": "texto", "items": [ { "object": "sale_item", "id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "product_id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "variant_id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "item_kind": "texto", "description": "texto", "quantity": 5, "unit_price": 25900, "subtotal": 25900, "unit_cost": 1, "tax_class": "texto", "taxes": [ null ] } ], "invoices": [ { "id": "3f1c2e8d-7a10-4d0b-9a57-0b6f2f0e5c1d", "document_type": "electronic_invoice", "status": "texto", "cufe": "texto", "prefix": "texto", "number": 1 } ], "occurred_at": "2026-09-28T15:04:05.000Z", "created_at": "2026-09-28T15:04:05.000Z", "updated_at": "2026-09-28T15:04:05.000Z" }ErroresTodo error responde con un objeto Error y un request_id. Ramifica por error.code, nunca por el mensaje.400Petición inválida (VALIDATION_ERROR, INVALID_JSON, INVALID_CURSOR).Cuerpo: un objeto Error. Qué significa cada código y qué hacer: Errores.VALIDATION_ERRORINVALID_JSONINVALID_CURSOR401Sin API key válida (UNAUTHENTICATED, INVALID_API_KEY, API_KEY_REVOKED, API_KEY_EXPIRED, API_KEY_WRONG_ENVIRONMENT, ACCOUNT_INACTIVE).Cuerpo: un objeto Error. Qué significa cada código y qué hacer: Errores.UNAUTHENTICATEDINVALID_API_KEYAPI_KEY_REVOKEDAPI_KEY_EXPIREDAPI_KEY_WRONG_ENVIRONMENTACCOUNT_INACTIVE403Sin permiso (PLAN_REQUIRED, INSUFFICIENT_SCOPE, BROWSER_REQUESTS_NOT_ALLOWED).Cuerpo: un objeto Error. Qué significa cada código y qué hacer: Errores.PLAN_REQUIREDINSUFFICIENT_SCOPEBROWSER_REQUESTS_NOT_ALLOWED404No existe en esta cuenta (NOT_FOUND).Cuerpo: un objeto Error. Qué significa cada código y qué hacer: Errores.NOT_FOUND429Límite de peticiones (RATE_LIMITED). Respeta Retry-After.Cuerpo: un objeto Error. Qué significa cada código y qué hacer: Errores.RATE_LIMITED500Error interno (INTERNAL_ERROR). Reintenta y comparte el request_id si persiste.Cuerpo: un objeto Error. Qué significa cada código y qué hacer: Errores.INTERNAL_ERROR