Por dónde sale
Elige si el comprobante va directo a SUNAT, por el OSE de la empresa o por nuestro OSE.
Autenticación: token Bearer de cuenta (empresas:manage).
Consideraciones
sunat(por defecto): directo a SUNAT con nuestras credenciales de PSE.own_ose: por el OSE que la empresa ya tiene contratado. Exigeose_username,ose_password,ose_url_productionyose_url_demo: sin los cuatro no hay a quién enviar.provider_ose: por nuestro OSE. Consume el paquete de envíos de la cuenta, y solo cuando el OSE recibe el comprobante: un rebote por credenciales o autorización no se cobra.- Salir por nuestro OSE necesita que la empresa lo vincule ante SUNAT (menú SOL 11.14.1.1.1). Con la clave SOL del principal cargada se hace solo; el estado se ve en
sunat_procedures.ose. - Si hay comprobantes firmados y sin enviar, la respuesta trae un
warning: saldrán por el destino nuevo. - Con firma externa el único destino válido es
provider_ose: cualquier otro responde422.
Para qué sirve
Son tres caminos hacia SUNAT y la empresa elige uno. Por defecto va directo a
SUNAT, que funciona sin configurar nada más. Si la empresa ya tiene un OSE
contratado, puede seguir usándolo (own_ose). Y si quiere que nosotros
llevemos también la recepción, sale por nuestro OSE (provider_ose).
Hasta ahora esto solo se elegía en el panel. Quien integraba por API y quería salir por nuestro OSE tenía que entrar a la web.
Qué consume el paquete de envíos
Por provider_ose, cada envío consume del paquete de la cuenta: un comprobante
es 1; un resumen diario es 1 más cada boleta que lleva.
El envío se cobra cuando el OSE recibe el comprobante y se pronuncia: aceptado, observado, rechazado, o con ticket. Un rebote porque el OSE todavía no tiene credenciales o no está vinculado ante SUNAT no se cobra, y reenviarlo tampoco.
El trámite ante SUNAT
Salir por nuestro OSE necesita que el contribuyente lo vincule en el portal
de SUNAT (menú SOL 11.14.1.1.1) con la clave del usuario principal. Sin eso
SUNAT rechaza los comprobantes con el código 0154.
Dos formas de hacerlo:
- Cargar la clave SOL del principal y dejar
que se haga solo.
sunat_procedures.osepasa dependingadone. - Hacerlo a mano en el portal. El botón «Verificar altas SUNAT» del panel lo comprueba después.
Lo que hay en vuelo
El destino se lee al enviar, no al firmar. Si al cambiarlo hay comprobantes
firmados y sin enviar, saldrán por el destino nuevo; la respuesta lo avisa en
warning. No se impide: a veces se cambia de destino precisamente porque el
anterior dejó de funcionar.
Headers
| Name | Type | Description |
|---|---|---|
| Accept | string | application/json |
| Content-Type | string | application/json |
| Authorization | string | Bearer <token>. Genéralo desde tu panel, en Tokens de API. |
Parámetros de URL
| Name | Type | Description |
|---|---|---|
| ruc* | string | RUC de 11 dígitos de la empresa. |
Body
| Name | Type | Description |
|---|---|---|
| destination* | string | sunat (por defecto) · own_ose · provider_ose. |
| ose_username | string | Usuario del OSE de la empresa. Obligatorio con own_ose. |
| ose_password | string | Clave del OSE de la empresa. Obligatoria con own_ose. |
| ose_url_production | string | Endpoint de producción del OSE de la empresa. Obligatorio con own_ose. |
| ose_url_demo | string | Endpoint de demo del OSE de la empresa. Obligatorio con own_ose. |
Ejemplo de solicitud
curl -X PATCH https://api.xmlperu.dev/v1/companies/20123456789/destination \
-H "Authorization: Bearer $TOKEN_CUENTA" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"destination": "provider_ose"
}'<?php
$token_cuenta = 'pega-aqui-tu-token';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.xmlperu.dev/v1/companies/20123456789/destination');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $token_cuenta,
'Accept: application/json',
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, <<<JSON
{
"destination": "provider_ose"
}
JSON);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);const TOKEN_CUENTA = 'pega-aqui-tu-token';
const res = await fetch('https://api.xmlperu.dev/v1/companies/20123456789/destination', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${TOKEN_CUENTA}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"destination": "provider_ose"
}),
});
const data = await res.json();import requests
TOKEN_CUENTA = "pega-aqui-tu-token"
headers = {
"Authorization": f"Bearer {TOKEN_CUENTA}",
"Accept": "application/json",
}
payload = {
"destination": "provider_ose"
}
res = requests.patch("https://api.xmlperu.dev/v1/companies/20123456789/destination", json=payload, headers=headers)
data = res.json()Respuesta
{
"success": true,
"message": "Destino de envío actualizado.",
"data": {
"company": {
"ruc": "20123456789",
"business_name": "MI EMPRESA SAC",
"plan_type": "01",
"environment": "02",
"environment_name": "production",
"destination": "provider_ose",
"signing": "provider",
"sol_credentials": true,
"sunat_procedures": { "pse": "done", "ose": "pending" },
"is_active": true
},
"warning": "Hay 3 comprobantes firmados y sin enviar que saldrán por OSE del proveedor en vez de SUNAT directo."
}
}provider_ose.{
"success": false,
"message": "La firma en el sistema del cliente (signing: external) solo está disponible enviando por nuestro OSE (destination: provider_ose): es lo único que entonces consume la empresa."
}