Skip to content

PRO REST API

REST API en el espacio de nombres polski-pro/v1 para gestionar facturas, ajustes y documentos legales. Requiere autenticación y la capacidad manage_woocommerce.

La API requiere dos elementos de autorización:

  1. Nonce de WordPress - la cabecera X-WP-Nonce con un valor generado por wp_create_nonce('wp_rest')
  2. Capacidad - el usuario que ha iniciado sesión debe tener la capacidad manage_woocommerce
const response = await fetch('/wp-json/polski-pro/v1/invoices', {
headers: {
'X-WP-Nonce': wpApiSettings.nonce,
'Content-Type': 'application/json',
},
});
$nonce = wp_create_nonce('wp_rest');
$response = wp_remote_get(
rest_url('polski-pro/v1/invoices'),
[
'headers' => [
'X-WP-Nonce' => $nonce,
],
]
);

Una solicitud sin un nonce válido la rechaza el propio WordPress con rest_cookie_invalid_nonce. Una solicitud autenticada cuyo usuario no tenga manage_woocommerce recibe 403 Forbidden con el código de error polski_pro_forbidden.

GET /wp-json/polski-pro/v1/invoices

Parámetros de consulta:

ParámetroTipoPredeterminadoDescripción
pageint1Número de página
per_pageint20Resultados por página (limitado a 100)
statusstringningunoFiltro de estado: draft, issued, sent, paid, cancelled
typestringningunoFiltro de tipo: faktura_vat, proforma, korygujaca, paragon, packing_slip
order_idintningunoFiltrar por ID de pedido de WooCommerce

Estos cinco son todos los parámetros registrados. No hay filtro por fechas ni búsqueda por texto: para acotar por periodo, filtre en su propio cliente sobre el campo issued_at.

Respuesta (200 OK):

El cuerpo es un array simple de objetos de factura. Los recuentos vuelven en las cabeceras X-WP-Total y X-WP-TotalPages, no en el cuerpo. Las entradas de la lista no llevan líneas: items solo lo rellena el endpoint de la factura individual.

[
{
"id": 1,
"order_id": 567,
"original_invoice_id": null,
"source_refund_id": null,
"type": "faktura_vat",
"type_label": "Faktura VAT",
"number": "FV/2026/04/001",
"status": "issued",
"status_label": "Issued",
"nip_seller": "9876543210",
"nip_buyer": "1234567890",
"buyer_name": "Firma Testowa Sp. z o.o.",
"buyer_address": "ul. Testowa 1",
"buyer_city": "Warszawa",
"buyer_postcode": "00-001",
"correction_reason": null,
"net_total": 1000.00,
"vat_total": 230.00,
"gross_total": 1230.00,
"currency": "PLN",
"pdf_path": "/wp-content/uploads/polski-pro/invoices/FV-2026-04-001.pdf",
"ksef_reference": null,
"ksef_status": null,
"issued_at": "2026-04-01T10:30:00+02:00",
"created_at": "2026-04-01T10:30:00+02:00",
"items": []
}
]
POST /wp-json/polski-pro/v1/invoices

Parámetros del cuerpo (JSON):

ParámetroTipoObligatorioDescripción
order_idintID de pedido de WooCommerce
typestringNoTipo: faktura_vat (predeterminado), proforma, korygujaca, paragon, packing_slip

Solicitud:

{
"order_id": 567,
"type": "faktura_vat"
}

Respuesta (201 Created):

La factura creada, con la misma forma que las entradas de la lista anterior. Un type desconocido, un pedido inexistente o una creación fallida devuelven 400 con un campo message.

{
"id": 43,
"order_id": 567,
"original_invoice_id": null,
"source_refund_id": null,
"type": "faktura_vat",
"type_label": "Faktura VAT",
"number": "FV/2026/04/002",
"status": "issued",
"status_label": "Issued",
"nip_seller": "9876543210",
"nip_buyer": "1234567890",
"buyer_name": "Firma Testowa Sp. z o.o.",
"buyer_address": "ul. Testowa 1",
"buyer_city": "Warszawa",
"buyer_postcode": "00-001",
"correction_reason": null,
"net_total": 500.00,
"vat_total": 115.00,
"gross_total": 615.00,
"currency": "PLN",
"pdf_path": null,
"ksef_reference": null,
"ksef_status": null,
"issued_at": "2026-04-05T14:00:00+02:00",
"created_at": "2026-04-05T14:00:00+02:00",
"items": []
}
GET /wp-json/polski-pro/v1/invoices/{id}

Devuelve los datos completos de la factura, incluidas las líneas.

Respuesta (200 OK):

{
"id": 43,
"order_id": 567,
"original_invoice_id": null,
"source_refund_id": null,
"type": "faktura_vat",
"type_label": "Faktura VAT",
"number": "FV/2026/04/002",
"status": "issued",
"status_label": "Issued",
"nip_seller": "9876543210",
"nip_buyer": "1234567890",
"buyer_name": "Firma Testowa Sp. z o.o.",
"buyer_address": "ul. Testowa 1",
"buyer_city": "Warszawa",
"buyer_postcode": "00-001",
"correction_reason": null,
"net_total": 212.20,
"vat_total": 48.80,
"gross_total": 261.00,
"currency": "PLN",
"pdf_path": "/wp-content/uploads/polski-pro/invoices/FV-2026-04-002.pdf",
"ksef_reference": null,
"ksef_status": null,
"issued_at": "2026-04-05T14:00:00+02:00",
"created_at": "2026-04-05T14:00:00+02:00",
"items": [
{
"id": 91,
"product_id": 120,
"name": "Produkt testowy",
"quantity": 2,
"unit": "szt.",
"net_price": 100.00,
"vat_rate": 23,
"vat_amount": 46.00,
"gross_price": 246.00
},
{
"id": 92,
"product_id": null,
"name": "Dostawa - InPost Paczkomat",
"quantity": 1,
"unit": "szt.",
"net_price": 12.20,
"vat_rate": 23,
"vat_amount": 2.80,
"gross_price": 15.00
}
]
}

El nombre y la dirección del vendedor no forman parte de este payload. Proceden de los datos del vendedor en los ajustes de facturas, y en la propia factura solo se guarda nip_seller.

Respuesta (404 Not Found):

{
"message": "Invoice not found."
}
POST /wp-json/polski-pro/v1/invoices/{id}/pdf

Regenera el archivo PDF de la factura. El endpoint no admite parámetros de cuerpo: la plantilla y el idioma salen de los ajustes de facturas.

Respuesta (200 OK):

El objeto de factura actualizado, con pdf_path apuntando al archivo nuevo. Una factura inexistente devuelve 404, un pedido inexistente 400 y una generación fallida 500, cada uno con un campo message.

POST /wp-json/polski-pro/v1/invoices/{id}/ksef

Encola la factura para enviarla al Sistema Nacional de e-Facturas (KSeF) mediante Action Scheduler. El endpoint no admite parámetros de cuerpo y nada en el escritorio de WordPress lo llama: solo se alcanza desde un cliente REST.

La llamada termina en cuanto el trabajo queda encolado. Nunca devuelve en la propia respuesta un número de referencia de KSeF, un estado de KSeF ni un enlace al UPO, porque en ese momento no existe ninguno. Léalos más tarde en ksef_reference y ksef_status de la factura.

Antes de apoyarse en esto, lea Integración con KSeF: el cliente de la API está fijado al entorno de pruebas de KSeF y su flujo de autenticación no está comprobado de extremo a extremo.

Respuesta (202 Accepted):

{
"invoice": {
"id": 43,
"number": "FV/2026/04/002",
"status": "issued",
"ksef_reference": null,
"ksef_status": null
},
"message": "Invoice queued for KSeF submission."
}

El valor invoice es el objeto de factura completo mostrado arriba, recortado aquí a los campos que importan para esta llamada.

Otras respuestas:

CódigoCuándo
404No hay ninguna factura con ese ID
422El documento no es un documento contable. Solo faktura_vat y korygujaca son válidos, así que Paragon, Proforma y Packing Slip se rechazan aquí
409La factura ya lleva una referencia de KSeF, y una factura enviada solo se puede corregir, nunca reenviar
503Action Scheduler no está disponible, así que no se puede encolar nada
{
"message": "Paragon documents are not eligible for KSeF submission."
}
POST /wp-json/polski-pro/v1/invoices/{id}/correction

Crea una factura rectificativa vinculada a la factura de origen. Los importes rectificados se derivan del pedido y, cuando se indica, del reembolso de WooCommerce. Por este endpoint no se pueden escribir a mano las líneas rectificadas.

Parámetros del cuerpo (JSON):

ParámetroTipoObligatorioDescripción
refund_idintNoReembolso de WooCommerce en el que se basa la rectificación

Solicitud:

{
"refund_id": 981
}

Respuesta (201 Created):

La factura rectificativa, con la misma forma que cualquier otro objeto de factura. type es korygujaca, original_invoice_id apunta a la factura de origen y los totales son negativos.

{
"id": 44,
"order_id": 567,
"original_invoice_id": 43,
"source_refund_id": 981,
"type": "korygujaca",
"type_label": "Faktura korygujaca",
"number": "FK/2026/04/001",
"status": "issued",
"status_label": "Issued",
"correction_reason": "Zwrot 1 sztuki produktu",
"net_total": -100.00,
"vat_total": -23.00,
"gross_total": -123.00,
"currency": "PLN",
"ksef_reference": null,
"ksef_status": null,
"issued_at": "2026-04-05T15:00:00+02:00",
"created_at": "2026-04-05T15:00:00+02:00",
"items": []
}

Una factura de origen inexistente devuelve 404, y una rectificación que el servicio no puede construir devuelve 400.

GET /wp-json/polski-pro/v1/invoices/stats

Parámetros de consulta:

ParámetroTipoPredeterminadoDescripción
daysint30Número de días hacia atrás, limitado al intervalo de 1 a 365

days es el único parámetro registrado. No hay agrupación configurable.

Respuesta (200 OK):

El recuento y los importes se calculan sobre las facturas con created_at dentro del periodo. total_revenue suma el bruto de todo lo que no está cancelado, mientras que los importes de by_type sí incluyen las canceladas, así que total_revenue queda por debajo de esa suma en cuanto hay alguna factura cancelada. ksef_sent cuenta las facturas que ya tienen una referencia de KSeF. Los desgloses son listas, no objetos indexados.

{
"period_days": 30,
"total": 156,
"total_revenue": 146031.1,
"ksef_sent": 120,
"by_type": [
{ "type": "faktura_vat", "count": 150, "revenue": 152000.0 },
{ "type": "korygujaca", "count": 6, "revenue": -2278.9 }
],
"by_status": [
{ "status": "issued", "count": 120 },
{ "status": "sent", "count": 25 },
{ "status": "paid", "count": 8 },
{ "status": "cancelled", "count": 3 }
]
}

No hay ningún bloque de resumen adicional, ni desglose por tipo impositivo, ni serie temporal diaria. Si necesita cualquiera de esas cosas, constrúyalas a partir de la lista de facturas.

GET /wp-json/polski-pro/v1/settings
PUT /wp-json/polski-pro/v1/settings

Una sola ruta con un método de lectura y otro de edición. GET devuelve todos los ajustes PRO agrupados: cada clave de primer nivel es un grupo (invoices, ksef, nip, shipping, delivery_date, checkout, abandoned_carts, conditional_payments, product_feed, loyalty, sms, accounting), más una clave hints con los textos de ayuda del panel. El lado de escritura se registra con EDITABLE, así que acepta PUT, PATCH y POST por igual. Ambos lados exigen manage_woocommerce.

Parámetros del cuerpo (JSON):

No hay parámetro section ni envoltorio settings. El cuerpo son los grupos en el primer nivel, y solo se procesan los grupos presentes.

ClaveTipoDescripción
invoicesobjectDatos del vendedor, numeración, generación automática, adjuntos de correo
ksefobjectenabled, environment, api_token, auto_send
nipobjectcheckout_field, required, validate_gus
shippingobjectCredenciales de InPost, DPD, DHL y Poczta Polska
delivery_dateobjectCampo de fecha de entrega en el pago
checkoutobjectmultistep_enabled
abandoned_cartsobjectTiempos de abandono y correos de recuperación
conditional_paymentsobjectenabled, más rules y fees como cadenas JSON
product_feedobjectenabled, platforms, opciones del feed
loyaltyobjectReglas de puntos y canje
smsobjectProveedor, plantillas y notificaciones
accountingobjectProveedor y credenciales de wFirma, Fakturownia o iFirma

Solicitud:

{
"invoices": {
"auto_generate": true,
"auto_generate_statuses": "completed",
"numbering_format": "FV/{YYYY}/{MM}/{NR}",
"number_reset": "year",
"number_padding": 3,
"payment_deadline_days": 14
},
"ksef": {
"enabled": false,
"environment": "test",
"api_token": "",
"auto_send": false
}
}

Respuesta (200 OK):

El conjunto completo de ajustes tras guardar, con la misma forma que devuelve GET. No hay campo updated_at.

{
"invoices": {
"auto_generate": true,
"auto_generate_statuses": "completed",
"numbering_format": "FV/{YYYY}/{MM}/{NR}",
"number_reset": "year",
"number_padding": 3,
"payment_deadline_days": 14
},
"ksef": {
"enabled": false,
"environment": "test",
"api_token": "",
"auto_send": false
},
"nip": {
"checkout_field": true,
"required": false,
"validate_gus": true
}
}

Endpoint de generación de documentos legales

Section titled “Endpoint de generación de documentos legales”

Estos tres endpoints exigen manage_woocommerce. Solo hay tres tipos de documento: regulamin, polityka-prywatnosci y polityka-zwrotow. Un type fuera de esa lista devuelve 400.

GET /wp-json/polski-pro/v1/legal/variables

Devuelve las variables que aceptan las plantillas, los valores predeterminados leídos de WooCommerce y las etiquetas de los tipos de documento.

Respuesta (200 OK):

{
"required": {
"company_name": "Full company name",
"company_address": "Company address",
"company_nip": "NIP (tax ID)",
"company_regon": "REGON number",
"company_email": "Contact email",
"company_phone": "Contact phone",
"shop_url": "Shop URL",
"shop_name": "Shop name",
"bank_name": "Bank name",
"bank_account": "Bank account number"
},
"defaults": {
"company_name": "Mój Sklep",
"company_address": "ul. Sklepowa 5, 02-222 Warszawa",
"company_nip": "9876543210",
"company_regon": "",
"company_email": "[email protected]",
"company_phone": "",
"shop_url": "https://mojsklep.pl",
"shop_name": "Mój Sklep",
"bank_name": "",
"bank_account": ""
},
"types": {
"regulamin": "Regulamin sklepu",
"polityka-prywatnosci": "Polityka prywatnosci",
"polityka-zwrotow": "Prawo odstapienia / Polityka zwrotow"
}
}
POST /wp-json/polski-pro/v1/legal/generate

Genera el texto a partir de una plantilla y lo devuelve como vista previa. No guarda nada.

Parámetros del cuerpo (JSON):

ParámetroTipoObligatorioDescripción
typestringTipo de documento: regulamin, polityka-prywatnosci, polityka-zwrotow
variablesobjectNoPares clave-valor que sustituyen a los predeterminados. Predeterminado: {}

No hay objeto company_data, ni parámetro format, ni parámetro language. Los datos de la empresa se pasan como claves sueltas dentro de variables, y la salida es siempre el HTML de la plantilla en polaco.

Solicitud:

{
"type": "regulamin",
"variables": {
"company_name": "Mój Sklep Sp. z o.o.",
"company_nip": "9876543210",
"company_address": "ul. Sklepowa 5, 02-222 Warszawa",
"company_email": "[email protected]",
"company_phone": "+48 123 456 789"
}
}

Respuesta (200 OK):

{
"type": "regulamin",
"content": "<h1>Regulamin sklepu internetowego...</h1>...",
"variables_used": {
"company_name": "Mój Sklep Sp. z o.o.",
"company_nip": "9876543210",
"company_address": "ul. Sklepowa 5, 02-222 Warszawa",
"company_email": "[email protected]",
"company_phone": "+48 123 456 789"
}
}

variables_used recoge solo lo que usted envió, ya saneado. Los valores que no envíe se rellenan con los predeterminados en el momento de renderizar. Si falta la plantilla o sale vacía, la respuesta es 500.

POST /wp-json/polski-pro/v1/legal/publish

Genera el texto y lo guarda en una página de WordPress en estado borrador, luego enlaza esa página en los ajustes de Polski. Nunca publica nada por su cuenta: revise el borrador y publíquelo usted.

Parámetros del cuerpo (JSON):

ParámetroTipoObligatorioDescripción
typestringTipo de documento: regulamin, polityka-prywatnosci, polityka-zwrotow
variablesobjectNoIgual que en /legal/generate. Predeterminado: {}
page_idintNoPágina existente que se va a actualizar. Predeterminado: 0, que crea una nueva

Respuesta (201 Created):

{
"page_id": 412,
"edit_url": "https://mojsklep.pl/wp-admin/post.php?post=412&action=edit",
"view_url": "https://mojsklep.pl/?page_id=412",
"status": "draft",
"message": "Page created as draft. Review and publish when ready."
}

Los endpoints de facturas y de documentos legales no usan códigos de error con nombre. Ante un fallo devuelven el estado HTTP y un cuerpo escueto con un único campo message:

{
"message": "Invoice not found."
}
Código HTTPCuándo
400Tipo de factura desconocido, pedido inexistente, rectificación que no se puede construir, tipo de documento legal fuera de la lista
404No hay ninguna factura con ese ID
409La factura ya tiene una referencia de KSeF
422El documento no es contable, así que no puede ir a KSeF
500La generación del PDF falló, o la plantilla legal falta o sale vacía
503Action Scheduler no está disponible

El único código de error con nombre en el controlador de facturas es polski_pro_forbidden, que devuelve la comprobación de permisos. Al ser un WP_Error, ese sí llega con la forma estándar de la REST API de WordPress:

{
"code": "polski_pro_forbidden",
"message": "Insufficient permissions.",
"data": {
"status": 403
}
}

Fuera de ese, los endpoints de facturas y de documentos legales no exponen ningún otro código con nombre. Discrimine por el estado HTTP, no por un código.

No hay ningún límite global de solicitudes en la API PRO. El único limitador de toda la capa REST está en la búsqueda de datos de empresa en el GUS, y solo se aplica a quien no tenga manage_woocommerce:

POST /wp-json/polski-pro/v1/gus/lookup

Se cuenta por IP del cliente, con un máximo predeterminado de 10 consultas por hora. Al superarlo, la respuesta es 429 con el código de error polski_pro_rate_limited.

Ambos valores son ajustables con filtros:

// Ventana de conteo en segundos. Predeterminado: HOUR_IN_SECONDS.
add_filter('polski-pro/gus/rate_limit_window_seconds', fn () => 1800);
// Consultas permitidas por ventana. Predeterminado: 10.
add_filter('polski-pro/gus/rate_limit_max_attempts', fn () => 25);

Si devuelve 0 en cualquiera de los dos filtros, el limitador queda desactivado.

Esta página tiene únicamente carácter informativo y no constituye asesoramiento legal. Consulte a un abogado antes de la implementación. Polski for WooCommerce es software de código abierto (GPLv2) proporcionado sin garantía.