Partners
Bienvenido a la documentación oficial del API de Partners de factura.com. Esta sección está diseñada para que puedas automatizar y gestionar todo tu ecosistema de negocio de forma centralizada a través de nuestra API.
Documentación legacy
La documentación de la versión anterior de Partners está deprecada y ya no aparece en el menú lateral, pero seguirá disponible como referencia para integraciones existentes en Partners legacy.
Con este módulo, tendrás el control total para integrar las siguientes capacidades en tu plataforma:
- Gestión de Clientes: Crea, actualiza y administra a tus clientes de manera segura.
- Control de Planes: Maneja tus diferentes planes paquetes que ofrecerás al mercado.
- Administración de Suscripciones: Controla el ciclo de vida completo de las suscripciones de tus clientes.
Para el API de Partners, es necesario utilizar un metodo de autenticación basado en tokens para poder hacer peticiones.
Especificación OpenAPI
Ponemos a tu disposición la especificación OpenAPI 3.1 del API de Partners. Con ella puedes generar SDKs, autocompletar peticiones o importar todos los endpoints en tu cliente de API favorito (Postman, Insomnia, Swagger, Scalar, etc.).
Cómo importarla
- Postman: Import → pestaña File (sube el
.jsono.yaml) o pega la URL de descarga. - Insomnia: Create → Import From → URL/File y selecciona el archivo.
- Swagger Editor / Swagger UI: usa el botón Abrir en Swagger Editor o File → Import URL.
- Scalar: desde scalar.com crea una referencia e importa la URL del
.json.
El mismo enlace de descarga está disponible en la barra de navegación superior mientras estés en esta página.
Host y modo sandbox
Todas las peticiones al API de Partners utilizan el mismo dominio para producción y sandbox:
Host: https://api-partners.factura.com/api
En los ejemplos de codigo es necesario reemplazar {HOST} por el que mencionamos arriba.
Para enviar una petición al ambiente sandbox, agrega el siguiente header:
F-Sandbox-Mode: true
Si envías F-Sandbox-Mode: false o no envías el header, la petición se procesará en producción.
Credenciales exclusivas para Sandbox
El modo Sandbox utiliza credenciales independientes de las de producción. Antes de hacer peticiones en este ambiente debes:
- Habilitar el modo Sandbox desde tu Panel de Partners en Configuración → Sandbox.
- Generar tus credenciales de API de Sandbox (Client ID y API Secret) en Configuración → API.
Usa estas credenciales de Sandbox para obtener tu token de acceso cuando envíes el header F-Sandbox-Mode: true. Las credenciales de producción no funcionan en Sandbox y viceversa.
Proceso de autenticación
A diferencia del resto de la API global de Factura.com, el API de Partners se autentica mediante el estándar OAuth 2.0, usando específicamente el flujo Client Credentials (grant_type: client_credentials).
Este flujo está diseñado para comunicación servidor a servidor (machine-to-machine): tu aplicación se identifica con sus propias credenciales —Client ID y API Secret— sin que intervenga ningún usuario final ni se requiera redirección a un navegador. A cambio, recibes un token de acceso (Bearer Token) de vida limitada que deberás incluir en cada petición a los endpoints protegidos.
En resumen, el ciclo de autenticación es:
- Obtén tus credenciales de aplicación (Client ID y API Secret) una sola vez desde tu Panel de Partners.
- Genera un token de acceso enviando esas credenciales al endpoint
POST /v1/auth/token. - Usa el token en el header
Authorization: Bearer <access_token>de cada petición. - Renueva el token solicitando uno nuevo cuando esté por expirar (ver Renovación del token).
Paso 1: Obtener tus credenciales de aplicación (Client ID y API Secret)
Antes de realizar tu primera petición, necesitas generar tus credenciales exclusivas para el API de partners desde tu Panel Administrativo:
- Inicia sesión en tu cuenta de Factura.com para ingresar al Panel de Partners.
- Dirígete al menú de Configuración -> API.
- Haz clic en el botón Crear aplicación.
- El sistema te proporcionará dos valores únicos:
- Client ID (Identificador de tu aplicación)
- API Secret (Llave secreta de tu aplicación)
Aviso
El API SECRET se muestra una sola vez. Guárdalo en un lugar seguro. Por tu seguridad, no volveremos a mostrarlo, ya que solo almacenamos una versión encriptada en nuestros servidores.
Paso 2: Generar el Token de Acceso
Una vez que tengas tu Client ID y API Secret, deberás utilizar esa información en los siguiente parámetros.
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| grant_type | String | Requerido | En este campo, siempre debemos mandar: "client_credentials" |
| client_id | String | Requerido | Aqui debes colocar el Client_id que copiaste de la aplicación que creaste desde la interfaz de tu Panel de Partners. Ejemplo - |
| client_secret | String | Requerido | En este campo hay que agregar el API secret que obtenemos en la interfaz de tu Panel de Partners. Ejemplo - |
Construcción de la URL
Importante
Importante el metodo para agregar una referencia de pago es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/auth/token
Ejemplo: https://api-partners.factura.com/api/v1/auth/token
Ejemplo de solicitar el token de acceso
POST /v1/auth/token HTTP/1.1
Host: {HOST}
Accept: application/json
Content-Type: application/json
F-Sandbox-Mode: true
{
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/auth/token',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-Type: application/json',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/auth/token',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/auth/token"
payload = json.dumps({
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
})
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/auth/token")
http = Net::HTTP.new(url.host, url.port);
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request.body = JSON.dump({
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
})
response = http.request(request)
puts response.read_body
Respuesta
{
"token_type": "Bearer",
"expires_in": 31535999,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIwMTllZWMwZC0yMjhkLTcwYzgtYjE5MS0yMzliODFlMmQ1N2MiLCJqdGkiOiJiMzc0OTYyMmVmMWQ0NWU4YTljNzQ5YTE3MjJlZDQ4Zjg5NGJhZTZiMTgwYTFmMDI1YWEyMDJiMDNjNDI4NmE1MzRkM2Y5ZWF..."
}
{
"error": "invalid_client",
"error_description": "Client authentication failed"
}
Entendiendo la respuesta del token
La respuesta exitosa devuelve los siguientes campos:
| Campo | Tipo | Detalles |
|---|---|---|
| token_type | String | Tipo de token. Siempre será Bearer, por lo que debe enviarse como Authorization: Bearer <access_token>. |
| expires_in | Integer | Tiempo de vida del token en segundos, contado a partir del momento en que se emitió. Cuando este tiempo transcurre, el token deja de ser válido y debes generar uno nuevo. |
| access_token | String | El token de acceso que usarás para autenticar tus peticiones. Trátalo como información sensible (equivale a una contraseña) y nunca lo expongas en código de cliente público. |
Uso del token en tus peticiones
Una vez obtenido, incluye el access_token en el header Authorization de todas las peticiones a los endpoints protegidos del API de Partners:
GET /v1/products HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
Si el token es inválido, está mal formado o ya expiró, el API responderá con un estatus 401 No autenticado. En ese caso deberás generar un nuevo token.
Renovación del token
El flujo Client Credentials de OAuth 2.0 no emite un refresh_token. Esto significa que no existe un endpoint de "refresco": para renovar el acceso simplemente vuelves a solicitar un token al mismo endpoint POST /v1/auth/token, reutilizando tu Client ID y API Secret.
Recomendaciones para gestionar el ciclo de vida del token de forma eficiente:
- Reutiliza el token mientras siga vigente. No solicites uno nuevo en cada petición; cada token es válido durante el número de segundos indicado en
expires_in. - Almacena el token y su fecha de expiración. Guarda el
access_tokenjunto con el instante en que lo obtuviste y el valor deexpires_in. Calcula su vencimiento comomomento_de_emisión + expires_in. - Solicita un nuevo token de forma anticipada. Idealmente renueva el token un poco antes de que expire (por ejemplo, con un margen de unos minutos) para evitar peticiones fallidas por una expiración a mitad de operación.
- Maneja el 401 de forma reactiva. Si una petición devuelve
401 No autenticado, genera un token nuevo y reintenta la operación una sola vez.
Consejos
Como el access_token reemplaza por completo al anterior, no necesitas invalidar el token previo: basta con empezar a usar el nuevo. Cada vez que generas un token, el contador de expires_in se reinicia.
Consultar tus planes
Este endpoint permite obtener un listado paginado de todos los planes (productos) que has creado y configurado previamente desde tu panel de control.
El endpoint incluye soporte nativo para paginación, filtros de búsqueda por nombre y ordenamiento avanzado, lo que te permite optimizar la carga de datos en tu plataforma.
Construcción de la URL
Importante
Importante el metodo para agregar una referencia de pago es GET
Host: https://api-partners.factura.com/api
Endpoint: v1/products
Ejemplo: https://api-partners.factura.com/api/v1/products
Utilice los siguientes parámetros opcionales en la URL para filtrar los resultados por nombre del plan, o para aplicar paginación u ordenamiento en la respuesta:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| name | string | Opcional | Indica el nombre del plan que se quiere consultar, puede estar completo o no. Ejemplo: /api/v1/products?name=paquete |
| sort | string | Opcional | Define el orden de los resultados. Utiliza el prefijo Ejemplo: /api/v1/products?sort=+sales |
| per_page | Integer | Opcional | Indica el limite de resultados para mostrar, por default retorna todos los planes del catálogo. Ejemplo: /api/v1/products?per_page=3 |
| page | Integer | Opcional | Indica número de página a consultar, por default posiciona en la página 1. Ejemplo: /api/v1/products?page=2 |
Ejemplo de petición
GET /v1/products HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/products',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'GET',
'url': '{ HOST }/v1/products',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/products"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"products": [
{
"uuid": "a21062196ea748e4a3e08280765fab75",
"name": "PLAN adicional",
"services": {
"api": false,
"smtp": true,
"custom_email": false,
"auto_invoices": false,
"invoices_migrator": false,
"clients": 0,
"extra_rfc": 0,
"extra_user": 0
},
"sales": 1,
"expiration_type": 0,
"status": "active",
"vigencies": [
{
"uuid": "a2106219c219440d8d03836f8d51171e",
"folios": 60,
"price": "400.00",
"expiration_period": "Sin periodicidad de expiración"
}
],
"pdf_templates": [
"default",
"classic",
"formal"
]
},
],
"pagination": {
"currentPage": 1,
"lastPage": 1,
"perPage": 15,
"total": 5
}
}
}
{
"status": "error",
"message": "Unauthenticated.",
"code": "SERVER_ERROR"
}
Parámetros de respuesta
| Parámetro | Tipo | Detalles |
|---|---|---|
| response | String | Estado general de la respuesta. |
| data.products | Array | Listado de productos o planes encontrados. |
| data.products[] | Object | Objeto con la información de cada producto. |
| data.products[].uuid | String | UUID del producto. |
| data.products[].name | String | Nombre del producto. |
| data.products[].services | Object | Configuración de servicios del producto. |
| data.products[].services.api | Booleano | Indica si el producto incluye acceso a la API. |
| data.products[].services.smtp | Booleano | Indica si el producto incluye servicio SMTP. |
| data.products[].services.custom_email | Booleano | Indica si el producto incluye correo personalizado. |
| data.products[].services.auto_invoices | Booleano | Indica si el producto incluye autofacturación. |
| data.products[].services.invoices_migrator | Booleano | Indica si el producto incluye migrador de facturas. |
| data.products[].services.clients | Numérico | Cantidad de clientes incluidos. |
| data.products[].services.extra_rfc | Numérico | Cantidad de RFC adicionales incluidos. |
| data.products[].services.extra_user | Numérico | Cantidad de usuarios adicionales incluidos. |
| data.products[].sales | Numérico | Cantidad de ventas asociadas al producto. |
| data.products[].expiration_type | Numérico | Tipo de expiración configurado para el producto. |
| data.products[].status | String | Estatus actual del producto. |
| data.products[].vigencies | Array | Listado de vigencias disponibles para el producto. |
| data.products[].vigencies[] | Object | Objeto con la información de cada vigencia. |
| data.products[].vigencies[].uuid | String | UUID de la vigencia. |
| data.products[].vigencies[].folios | Numérico | Cantidad de folios incluidos en la vigencia. |
| data.products[].vigencies[].price | String | Precio configurado para la vigencia. |
| data.products[].vigencies[].expiration_period | String | Periodo de expiración de la vigencia. |
| data.products[].pdf_templates | Array | Lista de plantillas PDF autorizadas. |
| data.products[].pdf_templates[] | String | Nombre de cada plantilla PDF autorizada. |
| data.pagination | Object | Información de paginación del listado. |
| data.pagination.currentPage | Numérico | Página actual de resultados. |
| data.pagination.lastPage | Numérico | Última página disponible. |
| data.pagination.perPage | Numérico | Cantidad de elementos por página. |
| data.pagination.total | Numérico | Total de productos encontrados. |
Crear planes
Este endpoint permite registrar un nuevo plan (producto) dentro de tu catálogo desde la API. Al crearlo, puedes definir su vigencia, precios, folios incluidos y activar o desactivar características específicas (servicios) que tendrá disponibles el cliente que adquiera dicho plan.
Podemos crear un nuevo plan haciendo uso de los siguientes parámetros:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| name | String | Requerido | Sirve para indicar el nombre que queremos ponerle al plan. |
| vigencies | Array | Requerido | Nodo para definir el tipo de vigencia y el tiempo del plan, la cantidad de folios y el precio. |
| vigencies[].folios | Numérico | Requerido | Elemento para indicar cuantos folios cargara el plan al clinete. |
| vigencies[].vigency | String | Requerido | Periodo de validez del plan. Valores aceptados: • "Mensual"• "Trimestral"• "Semestral"• "Anual"• "SP" (sin periodicidad) |
| vigencies[].price | Numérico | Requerido | Elemento para marcar el precio del plan. Esto servira para tus estadisticas mensuales. |
| services | Objeto | Requerido | Nodo contenedor con las configuraciones y características técnicas activas en el plan. Las funciones que se envíen como true (ej. smtp_mail) dependen estrictamente de que el Partner las tenga incluidas en su plan. |
| services.api | Booleano | Opcional | Define si la cuenta tendrá habilitado el acceso a las funciones de la API. |
| services.smtp_mail | Booleano | Opcional | Indica si la cuenta a crearse tendrá habilitadas las funciones de smtp para email. |
| services.custom_email | Booleano | Opcional | Indica si la cuenta a crearse tendrá habilitadas las funciones de un email personalizado. |
| services.pdf_templates | Array | Requerido | Lista de cadenas con los nombres de las plantillas PDF autorizadas para el plan (ej. "default", "classic"). |
| services.pdf_templates[] | String | Requerido | Nombre de cada plantilla PDF autorizada para el plan. |
| services.invoices_migrator | Booleano | Opcional | Activa la herramienta interna para migrar facturas o CFDI previos de los clientes. |
| services.auto_invoice | Booleano | Opcional | Indica si se habilita el autofacturador para el usuario. |
| services.extra_rfc | Numérico | Opcional | Se ingresa el número de los RFC extra que se desean agregar a la cuenta. |
| services.extra_user | Numérico | Opcional | Se ingresa la Cantidad de usuarios adicionales que pueden tener acceso a la cuenta. |
Construcción de la URL
Importante
Importante el metodo para agregar una referencia de pago es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/products
Ejemplo: https://api-partners.factura.com/api/v1/products
Ejemplo de crear plan
POST /v1/products HTTP/1.1
Host: {HOST}
Accept: application/json
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"name": "Plan especial",
"vigencies": [
{
"folios": 50,
"vigency": "Mensual",
"price": 490.00
}
],
"services": {
"api": false,
"smtp_mail": true,
"custom_email": true,
"pdf_templates": ["default", "classic"],
"invoices_migrator": false,
"auto_invoice": false,
"extra_rfc": 3,
"extra_user": 1
}
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/products',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"name": "Plan especial",
"vigencies": [
{
"folios": 50,
"vigency": "Mensual",
"price": 490.00
}
],
"services": {
"api": false,
"smtp_mail": true,
"custom_email": true,
"pdf_templates": [
"default",
"classic"
],
"invoices_migrator": false,
"auto_invoice": false,
"extra_rfc": 3,
"extra_user": 1
}
}',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/products',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"name": "Plan especial",
"vigencies": [
{
"folios": 50,
"vigency": "Mensual",
"price": 490
}
],
"services": {
"api": false,
"smtp_mail": true,
"custom_email": true,
"pdf_templates": [
"default",
"classic"
],
"invoices_migrator": false,
"auto_invoice": false,
"extra_rfc": 3,
"extra_user": 1
}
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/products"
payload = json.dumps({
"name": "Plan especial",
"vigencies": [
{
"folios": 50,
"vigency": "Mensual",
"price": 490
}
],
"services": {
"api": False,
"smtp_mail": True,
"custom_email": True,
"pdf_templates": [
"default",
"classic"
],
"invoices_migrator": False,
"auto_invoice": False,
"extra_rfc": 3,
"extra_user": 1
}
})
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/products")
http = Net::HTTP.new(url.host, url.port);
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"name": "Plan especial",
"vigencies": [
{
"folios": 50,
"vigency": "Mensual",
"price": 490
}
],
"services": {
"api": false,
"smtp_mail": true,
"custom_email": true,
"pdf_templates": [
"default",
"classic"
],
"invoices_migrator": false,
"auto_invoice": false,
"extra_rfc": 3,
"extra_user": 1
}
})
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"name": "Plan 3",
"services": {
"api": false,
"smtp": false,
"custom_email": false,
"auto_invoices": false,
"invoices_migrator": false,
"clients": 0,
"extra_rfc": 0,
"extra_user": 0
},
"sales": 0,
"expiration_type": false,
"status": null,
"vigencies": [
{
"uuid": "a2151fa2968e4879b029cc095d5e35f6",
"folios": 50,
"price": "490.00",
"expiration_period": "Mensual"
}
],
"pdf_templates": [
"default"
]
}
}
{
"status": "error",
"message": "Error de validación de datos.",
"errors": {
"services.pdf_templates": [
"The services.pdf templates field is required."
]
},
"code": "VALIDATION_FAILED"
}
Actualizar plan
Este endpoint permite modificar y actualizar la configuración de un plan (producto) ya existente dentro de tu catálogo desde la API. A través de esta petición, puedes editar de forma dinámica el nombre del plan, ajustar sus esquemas de vigencia y precios, o reconfigurar las características y servicios técnicos que tus clientes tendrán activos al adquirir o renovar dicho plan.
Para poder actualizar un plan existende podemos usar los siguientes parámetros:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| name | String | Requerido | Sirve para indicar el nombre que queremos ponerle al plan. |
| vigencies | Array | Requerido | Nodo para definir el tipo de vigencia y el tiempo del plan, la cantidad de folios y el precio. |
| vigencies[].folios | Numérico | Requerido | Elemento para indicar cuantos folios cargara el plan al clinete. |
| vigencies[].vigency | String | Requerido | Periodo de validez del plan. Valores aceptados: • "Mensual"• "Trimestral"• "Semestral"• "Anual"• "SP" (sin periodicidad) |
| vigencies[].price | Numérico | Requerido | Elemento para marcar el precio del plan. Esto servira para tus estadisticas mensuales. |
| services | Objeto | Requerido | Nodo contenedor con las configuraciones y características técnicas activas en el plan. Las funciones que se envíen como true (ej. smtp_mail) dependen estrictamente de que el Partner las tenga incluidas en su plan. |
| services.api | Booleano | Opcional | Define si la cuenta tendrá habilitado el acceso a las funciones de la API. |
| services.smtp_mail | Booleano | Opcional | Indica si la cuenta a crearse tendrá habilitadas las funciones de smtp para email. |
| services.custom_email | Booleano | Opcional | Indica si la cuenta a crearse tendrá habilitadas las funciones de un email personalizado. |
| services.pdf_templates | Array | Requerido | Lista de cadenas con los nombres de las plantillas PDF autorizadas para el plan (ej. "default", "classic"). |
| services.pdf_templates[] | String | Requerido | Nombre de cada plantilla PDF autorizada para el plan. |
| services.invoices_migrator | Booleano | Opcional | Activa la herramienta interna para migrar facturas o CFDI previos de los clientes. |
| services.auto_invoice | Booleano | Opcional | Indica si se habilita el autofacturador para el usuario. |
| services.extra_rfc | Numérico | Opcional | Se ingresa el número de los RFC extra que se desean agregar a la cuenta. |
| services.extra_user | Numérico | Opcional | Se ingresa la Cantidad de usuarios adicionales que pueden tener acceso a la cuenta. |
Construcción de la URL
Importante
Importante el metodo para agregar una referencia de pago es PATCH
Host: https://api-partners.factura.com/api
Endpoint: v1/products/UUID del plan
Ejemplo: https://api-partners.factura.com/api/v1/products/a2151fa2877f4d0a9781aa3fa275c0d6
Ejemplo de actualizar plan
PATCH /v1/products/{uuid} HTTP/1.1
Host: {HOST}
Accept: application/json
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"name": "PLAN EDITADO",
"vigencies": [
{
"folios": 60,
"vigency": "Trimestral",
"price": 790.00
}
],
"services": {
"api": true,
"smtp_mail": true,
"custom_email": true,
"auto_invoices": true,
"invoices_migrator": false,
"extra_rfc": 1,
"extra_user": 1,
"pdf_templates": ["default", "classic"]
}
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/products/a2151fa2877f4d0a9781aa3fa275c0d6',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS =>'{
"name": "PLAN EDITADO",
"vigencies": [
{
"folios": 60,
"vigency": "Trimestral",
"price": 790.00
}
],
"services": {
"api": true,
"smtp_mail": true,
"custom_email": true,
"auto_invoices": true,
"invoices_migrator": false,
"extra_rfc": 1,
"extra_user": 1,
"pdf_templates": ["default",
"classic"
]
}
}',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'PATCH',
'url': '{ HOST }/v1/products/a2151fa2877f4d0a9781aa3fa275c0d6',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"name": "PLAN EDITADO",
"vigencies": [
{
"folios": 60,
"vigency": "Trimestral",
"price": 790
}
],
"services": {
"api": true,
"smtp_mail": true,
"custom_email": true,
"auto_invoices": true,
"invoices_migrator": false,
"extra_rfc": 1,
"extra_user": 1,
"pdf_templates": [
"default",
"classic"
]
}
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/products/a2151fa2877f4d0a9781aa3fa275c0d6"
payload = json.dumps({
"name": "PLAN EDITADO",
"vigencies": [
{
"folios": 60,
"vigency": "Trimestral",
"price": 790
}
],
"services": {
"api": True,
"smtp_mail": True,
"custom_email": True,
"auto_invoices": True,
"invoices_migrator": False,
"extra_rfc": 1,
"extra_user": 1,
"pdf_templates": [
"default",
"classic"
]
}
})
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("PATCH", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/products/a2151fa2877f4d0a9781aa3fa275c0d6")
http = Net::HTTP.new(url.host, url.port);
https.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"name": "PLAN EDITADO",
"vigencies": [
{
"folios": 60,
"vigency": "Trimestral",
"price": 790
}
],
"services": {
"api": true,
"smtp_mail": true,
"custom_email": true,
"auto_invoices": true,
"invoices_migrator": false,
"extra_rfc": 1,
"extra_user": 1,
"pdf_templates": [
"default",
"classic"
]
}
})
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"name": "PLAN EDITADO",
"services": {
"api": true,
"smtp": true,
"custom_email": true,
"auto_invoices": true,
"invoices_migrator": false,
"clients": 5,
"extra_rfc": 1,
"extra_user": 1
},
"sales": 0,
"expiration_type": 0,
"status": "active",
"vigencies": [
{
"uuid": "a2152b157b4949fab99b1085bd4186b3",
"folios": 60,
"price": "790.00",
"expiration_period": "Trimestral"
}
],
"pdf_templates": [
"default",
"classic"
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Borrar planes
Este endpoint permite eliminar uno o múltiples planes (productos) de tu catálogo de forma masiva desde la API. Al realizar esta acción, los identificadores enviados dejarán de estar disponibles para nuevas asignaciones o suscripciones.
Podemos borrar planes haciendo uso de los siguientes parámetros:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| uuids | Array | Requerido | Mandar el UUID del plane que se desea eliminar. |
| uuids[] | String | Requerido | UUID del plan que se desea eliminar. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es DELETE
Host: https://api-partners.factura.com/api
Endpoint: v1/products
Ejemplo: https://api-partners.factura.com/api/v1/products
Ejemplo de borrar plan
DELETE /v1/products HTTP/1.1
Host: {HOST}
Accept: application/json
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"uuids": [
"a1e2019fe2b542af96caf6f9320781bd"
]
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/products',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_POSTFIELDS =>'{
"uuids": [
"a1e2019fe2b542af96caf6f9320781bd"
]
}',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'DELETE',
'url': '{ HOST }/v1/products',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"uuids": [
"a1e2019fe2b542af96caf6f9320781bd"
]
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/products"
payload = json.dumps({
"uuids": [
"a1e2019fe2b542af96caf6f9320781bd"
]
})
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("DELETE", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/products")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Delete.new(url)
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request.body = JSON.dump({
"uuids": [
"a1e2019fe2b542af96caf6f9320781bd"
]
})
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"products": [
{
"uuid": "a2151814db4d4ead827e708300b86792",
"name": "API ELIMINADO",
"services": {
"api": false,
"smtp": true,
"custom_email": true,
"auto_invoices": false,
"invoices_migrator": false,
"clients": 0,
"extra_rfc": 3,
"extra_user": 1
},
"sales": 0,
"expiration_type": 0,
"status": "inactive",
"vigencies": [
{
"uuid": "a21518150304451a866317c2503fc557",
"folios": 50,
"price": "490.00",
"expiration_period": "Trimestral"
}
],
"pdf_templates": [
"default",
"classic"
]
}
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Mostrar plan
Este endpoint permite obtener la información detallada de un plan (producto) específico de tu catálogo utilizando su identificador único (UUID). Es de gran utilidad para verificar de forma dinámica los folios, precios y servicios activos de un plan antes de asociarlo a un cliente.
Podemos consultar un plan haciendo uso de los siguientes parámetros de ruta:
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es GET
Host: https://api-partners.factura.com/api
Endpoint: v1/products/UUID del plan
Ejemplo: https://api-partners.factura.com/api/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c
Ejemplo de petición
GET /v1/products/{uuid} HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'GET',
'url': '{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"services": {
"api": true,
"smtp": true,
"custom_email": false,
"auto_invoices": false,
"invoices_migrator": false,
"clients": 0,
"extra_rfc": 0,
"extra_user": 0
},
"sales": 1,
"expiration_type": 1,
"status": "active",
"vigencies": [
{
"uuid": "a210621a4715406086913d91ae27c134",
"folios": 100,
"price": "700.00",
"expiration_period": "Anual"
}
],
"pdf_templates": [
"default",
"classic",
"formal",
"minimalist",
"trendy",
"elegant"
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Cambiar estatus de plan
Este endpoint permite activar (habilitar) o desactivar (deshabilitar) un plan (producto) específico de tu catálogo mediante su UUID. Deshabilitar un plan evitará que puedan ponérselo a un cliente.
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/products/UUID del plan/change-status
Ejemplo: https://api-partners.factura.com/api/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c/change-status
Ejemplo de petición
POST /v1/products/{uuid}/change-status HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c/change-status',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c/change-status',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c/change-status"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/products/a1390ee8e88e4b089e7bca82b1be5a0c/change-status")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a210621a54b142a8915f0f1a16afc83c",
"name": "NUEVO PLAN",
"services": {
"api": false,
"smtp": false,
"custom_email": false,
"auto_invoices": true,
"invoices_migrator": true,
"clients": 0,
"extra_rfc": "2",
"extra_user": "2"
},
"sales": 0,
"expiration_type": 1,
"status": "inactive",
"vigencies": [
{
"uuid": "a210621b0702489ca4037bcbd4796465",
"folios": 10,
"price": "100.00",
"expiration_period": "Semestral"
}
],
"pdf_templates": [
"default",
"classic",
"elegant"
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Consultar clientes
Este endpoint permite obtener un listado de todos los clientes registrados bajo tu cuenta de Partner.
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es GET
Host: https://api-partners.factura.com/api
Endpoint: v1/clients
Ejemplo: https://api-partners.factura.com/api/v1/clients
Utilice los siguientes parámetros opcionales en la URL para filtrar los resultados por nombre del cliente, o para aplicar paginación u ordenamiento en la respuesta:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| name | string | Opcional | Indica el nombre del cliente que se quiere consultar, puede estar completo o no. Ejemplo: /api/v1/clients?name=Escuela |
| sort | string | Opcional | Define el orden de los resultados. Utiliza el prefijo Ejemplo: /api/v1/clients?sort=+name |
| per_page | Integer | Opcional | Indica el límite de resultados para mostrar, por default retorna todos los planes del catalogo. Ejemplo: /api/v1/clients?per_page=3 |
| page | Integer | Opcional | Indica número de página a consultar, por default posiciona en la página 1. Ejemplo: /api/v1/clients?page=2 |
Ejemplo de petición
GET /v1/clients HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'GET',
'url': '{ HOST }/v1/clients',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/clients"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/clients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"clients": [
{
"uuid": "a210621c826a46499ef1000d64aeb402",
"name": " ",
"email": "[email protected]",
"status": "active",
"taxInformation": {
"legalName": "INDISTRIA ILUMINADORA ELITE",
"taxId": "IIA040805DZ0",
"taxRegime": null,
"useKey": null,
"zipCode": "62661",
"country": "MEX",
"state": "",
"city": "",
"neighborhood": "",
"address": "",
"additionalEmail": null
},
"subscription": null,
"createdAt": "2026-06-19T23:41:32.000000Z",
"updatedAt": "2026-06-19T23:41:32.000000Z"
},
{
"uuid": "a210621b15284f9db98e939008e775db",
"name": " ",
"email": "[email protected]",
"status": "suspended",
"taxInformation": {
"legalName": "CECILIA ELITE",
"taxId": "MISC491214B85",
"taxRegime": null,
"useKey": null,
"zipCode": "01010",
"country": "MEX",
"state": "Distrito Federal",
"city": "Álvaro Obregón",
"neighborhood": "",
"address": "",
"additionalEmail": null
},
"subscription": null,
"createdAt": "2026-06-19T23:41:31.000000Z",
"updatedAt": "2026-06-19T23:41:31.000000Z"
}
],
"pagination": {
"currentPage": 1,
"lastPage": 1,
"perPage": 15,
"total": 2
}
}
}
{
"status": "error",
"message": "Unauthenticated.",
"code": "SERVER_ERROR"
}
Mostrar cliente
Este endpoint permite obtener la información detallada de un solo cliente específico de tu catálogo utilizando su identificador único (UUID).
Podemos consultar un cliente haciendo uso de los siguientes parámetros de ruta:
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es GET
Host: https://api-partners.factura.com/api
Endpoint: v1/clients/UUID del cliente
Ejemplo: https://api-partners.factura.com/api/v1/clients/a23640b3d6a843fdb2c37df143931f5d
Ejemplo de petición
GET /v1/clients/{uuid} HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients/a1390ee8e88e4b089e7bca82b1be5a0c',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'GET',
'url': '{ HOST }/v1/clients/a1390ee8e88e4b089e7bca82b1be5a0c',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/clients/a1390ee8e88e4b089e7bca82b1be5a0c"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/clients/a1390ee8e88e4b089e7bca82b1be5a0c")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a23640b3d6a843fdb2c37df143931f5d",
"name": "Juan Lopez",
"email": "[email protected]",
"apiKey": "JDJ5J...",
"secretKey": "JDJ5...",
"token": "ZXlKc...",
"status": "suspended",
"taxInformation": {
"legalName": "INDUSTRIAS XA",
"taxId": "XIA190128J61",
"taxRegime": null,
"useKey": null,
"zipCode": "76343",
"country": "MEX",
"state": null,
"city": null,
"neighborhood": null,
"address": null,
"additionalEmail": null
},
"subscription": null,
"createdAt": "2026-07-08T19:29:34.000000Z",
"updatedAt": "2026-07-08T19:29:34.000000Z"
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Crear cliente
A continuación se explica la función para partners con la cual podrás crear cuentas para tus clientes y asignarles planes para que comiencen a facturar
Tip
Es importante tener configurados los planes en tu interfaz los cuales asignaras a los clientes que generes por API
Podemos crear un nuevo cliente haciendo uso de los siguientes parámetros:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| client | Objeto | Requerido | Nodo contenedor con la información general del cliente que se desea crear. |
| client.name | String | Requerido | Sirve para indicar el nombre del cliente que se registrará en el sistema. |
| client.email | String | Requerido | Correo electrónico principal del cliente. Este correo será utilizado para el acceso y recepción de notificaciones del sistema. |
| tax_information | Objeto | Requerido | Nodo que contiene la información fiscal del cliente para efectos de facturación. |
| tax_information.tax_id | String | Requerido | RFC del cliente que será utilizado para la emisión de CFDI. |
| tax_information.legal_name | String | Requerido | Razón social o nombre fiscal del cliente registrado ante el SAT. |
| tax_information.postal_code | String | Requerido | Código postal correspondiente al domicilio fiscal del cliente. |
| tax_information.invoice_use_key | String | Requerido | Clave de uso de CFDI que se asignará por defecto al cliente para la emisión de facturas. Ejemplo: "G01" |
| tax_information.tax_regime | String | Requerido | Clave del régimen fiscal correspondiente al cliente conforme al catálogo del SAT. |
| tax_information.country | String | Opcional | País correspondiente al domicilio fiscal del cliente. |
| tax_information.state | String | Opcional | Estado o entidad federativa correspondiente al domicilio fiscal del cliente. |
| tax_information.city | String | Opcional | Ciudad o municipio correspondiente al domicilio fiscal del cliente. |
| tax_information.neighborhood | String | Opcional | Colonia correspondiente al domicilio fiscal del cliente. |
| tax_information.address | String | Opcional | Dirección completa del domicilio fiscal del cliente. |
| tax_information.additional_email | String | Opcional | Correo electrónico adicional al que se podrán enviar documentos fiscales o notificaciones relacionadas con la facturación. |
| product | Objeto | Requerido | Nodo que contiene la información del producto o plan que será asignado al cliente. |
| product.uuid | String | Requerido | Es el UUID del plan que se asignará al cliente. |
| product.vigency_uuid | String | Requerido | Es el UUID de la vigencia asociada al producto seleccionado. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/clients
Ejemplo: https://api-partners.factura.com/api/v1/clients
Ejemplo para dar de alta un nuevo cliente
POST /v1/clients HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"client": {
"name": "MARTIN LOPEZ",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH1",
"legal_name": "MARTIN LOPEZ LOPEZ",
"postal_code": "01234",
"invoice_use_key": "G01",
"tax_regime": "601"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"vigency_uuid": "a210621a4715406086913d91ae27c134"
}
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"client": {
"name": "MARTIN LOPEZ",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH1",
"legal_name": "MARTIN LOPEZ LOPEZ",
"postal_code": "01234",
"invoice_use_key": "G01",
"tax_regime": "601"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"vigency_uuid": "a210621a4715406086913d91ae27c134"
}
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/clients',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"client": {
"name": "MARTIN LOPEZ",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH1",
"legal_name": "MARTIN LOPEZ LOPEZ",
"postal_code": "01234",
"invoice_use_key": "G01",
"tax_regime": "601"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"vigency_uuid": "a210621a4715406086913d91ae27c134"
}
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/clients"
payload = json.dumps({
"client": {
"name": "MARTIN LOPEZ",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH1",
"legal_name": "MARTIN LOPEZ LOPEZ",
"postal_code": "01234",
"invoice_use_key": "G01",
"tax_regime": "601"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"vigency_uuid": "a210621a4715406086913d91ae27c134"
}
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/clients")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"client": {
"name": "MARTIN LOPEZ",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH1",
"legal_name": "MARTIN LOPEZ LOPEZ",
"postal_code": "01234",
"invoice_use_key": "G01",
"tax_regime": "601"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"vigency_uuid": "a210621a4715406086913d91ae27c134"
}
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ",
"email": "[email protected]",
"status": null,
"taxInformation": {
"legalName": "MARTIN LOPEZ LOPEZ",
"taxId": "FUNK671228PH1",
"taxRegime": "601",
"useKey": "G01",
"zipCode": "01234",
"country": null,
"state": null,
"city": null,
"neighborhood": null,
"address": null,
"additionalEmail": null
},
"subscription": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"startDate": "2026-06-22T00:00:00.000000Z",
"endDate": "2026-07-22T00:00:00.000000Z",
"folios": 100,
"foliosUsed": 0,
"status": "active",
"services": {
"api": true,
"smtp": true,
"customEmail": false,
"extraCompanies": 0,
"extraUsers": 0
}
},
"createdAt": "2026-06-22T09:58:03.000000Z",
"updatedAt": "2026-06-22T09:58:04.000000Z"
}
}
{
"status": "error",
"message": "Error de validación de datos.",
"errors": {
"product.uuid": [
"The selected product.uuid is invalid."
]
},
"code": "VALIDATION_FAILED"
}
Suspender cliente
A continuación se explica la función para suspender a un cliente. Durante la suspensión podrás indicar el mensaje que recibirá el cliente y definir si los folios disponibles deben conservarse o regresar a tu panel de partner.
Estos son los parámetros para parámetros un cliente:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| uuids | Array | Requerido | UUID de cliente que sera suspendido. |
| uuids[] | String | Requerido | UUID del cliente que será suspendido. |
| message | String | Requerido | Mensaje que se enviara por correo del motivo de la suspensión de la cuenta al cliente. |
| keep_folios | Booleano | Requerido | Indica si los folios disponibles del cliente deberán conservarse después de realizar la suspensión. Valores aceptados: • true → Conserva los folios disponibles.• false → Elimina los folios disponibles al suspender la cuenta. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/clients/suspend
Ejemplo: https://api-partners.factura.com/api/v1/clients/suspend
Ejemplo para suspender cliente
POST /v1/clients/suspend HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"uuids": [
"a20840069eb541f79a70fd7522f27f1d"
],
"message": "Este es una suspensión de prueba por API",
"keep_folios": true
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients/suspend',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"uuids": [
"a20840069eb541f79a70fd7522f27f1d"
],
"message": "Este es una suspensión de prueba por API",
"keep_folios": true
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/clients/suspend',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"uuids": [
"a20840069eb541f79a70fd7522f27f1d"
],
"message": "Este es una suspensión de prueba por API",
"keep_folios": true
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/clients/suspend"
payload = json.dumps({
"uuids": [
"a20840069eb541f79a70fd7522f27f1d"
],
"message": "Este es una suspensión de prueba por API",
"keep_folios": True
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/clients/suspend")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"uuids": [
"a20840069eb541f79a70fd7522f27f1d"
],
"message": "Este es una suspensión de prueba por API",
"keep_folios": true
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"clients": [
{
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "CLIENTE MARTIN LOPEZ",
"email": "[email protected]",
"status": "suspended",
"taxInformation": {
"legalName": "MARTIN LOPEZ LOPEZ",
"taxId": "FUNK671228PH1",
"taxRegime": "601",
"useKey": "G01",
"zipCode": "01234",
"country": null,
"state": null,
"city": null,
"neighborhood": null,
"address": null,
"additionalEmail": null
},
"subscription": null,
"createdAt": "2026-06-22T09:58:03.000000Z",
"updatedAt": "2026-06-22T10:28:28.000000Z"
}
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Reactivar cliente
A continuación se explica la función para reactivar uno o múltiples clientes previamente suspendidos para que puedan volver a utilizar su cuenta y continuar operando normalmente.
Estos son los parámetros para reactivar clientes:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| uuids | Array | Requerido | UUID de uno o múltiples clientes que serán reactivados. |
| uuids[] | String | Requerido | UUID del cliente que será reactivado. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/clients/reactivate
Ejemplo: https://api-partners.factura.com/api/v1/clients/reactivate
Ejemplo para suspender cliente
POST /v1/clients/reactivate HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"uuids": [
"a1391c1fc8914e618413e476b52b4615"
]
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients/reactivate',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"uuids": [
"a1391c1fc8914e618413e476b52b4615"
]
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/clients/reactivate',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"uuids": [
"a1391c1fc8914e618413e476b52b4615"
]
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/clients/reactivate"
payload = json.dumps({
"uuids": [
"a1391c1fc8914e618413e476b52b4615"
]
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/clients/reactivate")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"uuids": [
"a1391c1fc8914e618413e476b52b4615"
]
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"clients": [
{
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "CLIENTE MARTIN LOPEZ",
"email": "[email protected]",
"status": "active",
"taxInformation": {
"legalName": "MARTIN LOPEZ LOPEZ",
"taxId": "FUNK671228PH1",
"taxRegime": "601",
"useKey": "G01",
"zipCode": "01234",
"country": null,
"state": null,
"city": null,
"neighborhood": null,
"address": null,
"additionalEmail": null
},
"subscription": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"startDate": "2026-06-22T00:00:00.000000Z",
"endDate": "2026-07-22T00:00:00.000000Z",
"folios": 100,
"foliosUsed": 0,
"status": "active",
"services": {
"api": true,
"smtp": true,
"customEmail": false,
"extraCompanies": 0,
"extraUsers": 0
}
},
"createdAt": "2026-06-22T09:58:03.000000Z",
"updatedAt": "2026-06-22T10:40:42.000000Z"
}
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Reenviar accesos al cliente
A continuación se explica la función para reenviar por correo electrónico los accesos de una cuenta previamente creada. Esta función permite volver a enviar al cliente la información de acceso utilizando el UUID de su cuenta.
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/clients/UUID del cliente/resend-credentials
Ejemplo: https://api-partners.factura.com/api/v1/clients/a1f9c3d9fee5434ebf6104e1de572b59/resend-credentials
Ejemplo de petición
POST /v1/clients/{uuid}/resend-credentials HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients/a1f9c3d9fee5434ebf6104e1de572b59/resend-credentials',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/clients/a1f9c3d9fee5434ebf6104e1de572b59/resend-credentials',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/clients/a1f9c3d9fee5434ebf6104e1de572b59/resend-credentials"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/clients/a1f9c3d9fee5434ebf6104e1de572b59/resend-credentials")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"clients": [
{
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "CLIENTE MARTIN LOPEZ",
"email": "[email protected]",
"status": "active",
"taxInformation": {
"legalName": "MARTIN LOPEZ LOPEZ",
"taxId": "FUNK671228PH1",
"taxRegime": "601",
"useKey": "G01",
"zipCode": "01234",
"country": null,
"state": null,
"city": null,
"neighborhood": null,
"address": null,
"additionalEmail": null
},
"subscription": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"startDate": "2026-06-22T00:00:00.000000Z",
"endDate": "2026-07-22T00:00:00.000000Z",
"folios": 100,
"foliosUsed": 0,
"status": "active",
"services": {
"api": true,
"smtp": true,
"customEmail": false,
"extraCompanies": 0,
"extraUsers": 0
}
},
"createdAt": "2026-06-22T09:58:03.000000Z",
"updatedAt": "2026-06-22T10:40:42.000000Z"
}
]
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Actualizar cliente
A continuación se explica la función para actualizar la información de una cuenta de cliente previamente creada. Con esta operación podrás modificar los datos generales y fiscales del cliente; sin embargo, el producto o plan asignado a la cuenta no podrá ser modificado desde este endpoint.
Estos son los parámetros para actualizar un cliente:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| client | Objeto | Opcional | Nodo contenedor con la información general del cliente que se desea actualizar. |
| client.name | String | Opcional | Sirve para indicar el nuevo nombre que tendrá registrado el cliente. |
| client.email | String | Opcional | Correo electrónico principal del cliente. Este correo será utilizado para el acceso y recepción de notificaciones del sistema. |
| tax_information | Objeto | Opcional | Nodo que contiene la información fiscal del cliente que será actualizada. |
| tax_information.tax_id | String | Opcional | RFC del cliente que será utilizado para la emisión de CFDI. |
| tax_information.legal_name | String | Opcional | Razón social o nombre fiscal del cliente registrado ante el SAT. |
| tax_information.postal_code | String | Opcional | Código postal correspondiente al domicilio fiscal del cliente. |
| tax_information.invoice_use_key | String | Opcional | Clave de uso de CFDI que se asignará al cliente para la emisión de facturas. Ejemplo: "G01" |
| tax_information.tax_regime | String | Opcional | Clave del régimen fiscal correspondiente al cliente conforme al catálogo del SAT. |
| tax_information.country | String | Opcional | País correspondiente al domicilio fiscal del cliente. |
| tax_information.state | String | Opcional | Estado o entidad federativa correspondiente al domicilio fiscal del cliente. |
| tax_information.city | String | Opcional | Ciudad o municipio correspondiente al domicilio fiscal del cliente. |
| tax_information.neighborhood | String | Opcional | Colonia correspondiente al domicilio fiscal del cliente. |
| tax_information.address | String | Opcional | Dirección completa correspondiente al domicilio fiscal del cliente. |
| tax_information.additional_email | String | Opcional | Correo electrónico adicional al que se podrán enviar documentos fiscales o notificaciones relacionadas con la facturación. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es PATCH
Host: https://api-partners.factura.com/api
Endpoint: v1/clients/UUID del cliente
Ejemplo: https://api-partners.factura.com/api/v1/clients/ra21544903d574f0c889798f8c13965cc
Ejemplo para actualizar cliente
PATCH /v1/clients/{uuid} HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"client": {
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH8",
"legal_name": "MARTIN EDITADO",
"postal_code": "01235",
"invoice_use_key": "G01",
"tax_regime": "626",
"country": "México",
"state": "Ciudad de México",
"city": "Ciudad de México",
"neighborhood": "Polanco",
"address": "Av. Reforma 123, Col. Polanco",
"additional_email": "[email protected]"
}
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/clients/a21544903d574f0c889798f8c13965cc',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"client": {
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH8",
"legal_name": "MARTIN EDITADO",
"postal_code": "01235",
"invoice_use_key": "G01",
"tax_regime": "626",
"country": "México",
"state": "Ciudad de México",
"city": "Ciudad de México",
"neighborhood": "Polanco",
"address": "Av. Reforma 123, Col. Polanco",
"additional_email": "[email protected]"
}
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/clients/a21544903d574f0c889798f8c13965cc',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"client": {
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH8",
"legal_name": "MARTIN EDITADO",
"postal_code": "01235",
"invoice_use_key": "G01",
"tax_regime": "626",
"country": "México",
"state": "Ciudad de México",
"city": "Ciudad de México",
"neighborhood": "Polanco",
"address": "Av. Reforma 123, Col. Polanco",
"additional_email": "[email protected]"
}
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/clients/a21544903d574f0c889798f8c13965cc"
payload = json.dumps({
"client": {
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH8",
"legal_name": "MARTIN EDITADO",
"postal_code": "01235",
"invoice_use_key": "G01",
"tax_regime": "626",
"country": "México",
"state": "Ciudad de México",
"city": "Ciudad de México",
"neighborhood": "Polanco",
"address": "Av. Reforma 123, Col. Polanco",
"additional_email": "[email protected]"
}
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/clients/a21544903d574f0c889798f8c13965cc")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"client": {
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]"
},
"tax_information": {
"tax_id": "FUNK671228PH8",
"legal_name": "MARTIN EDITADO",
"postal_code": "01235",
"invoice_use_key": "G01",
"tax_regime": "626",
"country": "México",
"state": "Ciudad de México",
"city": "Ciudad de México",
"neighborhood": "Polanco",
"address": "Av. Reforma 123, Col. Polanco",
"additional_email": "[email protected]"
}
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]",
"status": "active",
"taxInformation": {
"legalName": "MARTIN EDITADO",
"taxId": "FUNK671228PH8",
"taxRegime": "626",
"useKey": "G01",
"zipCode": "01235",
"country": "México",
"state": "Ciudad de México",
"city": "Ciudad de México",
"neighborhood": "Polanco",
"address": "Av. Reforma 123, Col. Polanco",
"additionalEmail": "[email protected]"
},
"subscription": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"startDate": "2026-06-22T00:00:00.000000Z",
"endDate": "2026-07-22T00:00:00.000000Z",
"folios": 100,
"foliosUsed": 0,
"status": "active",
"services": {
"api": true,
"smtp": true,
"customEmail": false,
"extraCompanies": 0,
"extraUsers": 0
}
},
"createdAt": "2026-06-22T09:58:03.000000Z",
"updatedAt": "2026-06-22T11:01:48.000000Z"
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Consultar suscripciones
A continuación se explica la función para consultar las suscripciones disponibles y obtener la información relacionada con los planes asignados a las cuentas de tus clientes. Esta consulta permite recuperar los detalles de la suscripción, incluyendo información sobre vigencias, estado y configuración asociada.
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es GET
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions
Utilice los siguientes parámetros opcionales en la URL para filtrar los resultados por nombre del plan que tiene la suscripción, o para aplicar paginación u ordenamiento en la respuesta:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| name | string | Opcional | Indica el nombre del plan que tiene la suscripción que se quiere consultar, puede estar completo o no. Ejemplo: /api/v1/subscriptions?name=Plan2026 |
| sort | string | Opcional | Define el orden de los resultados. Utiliza el prefijo Ejemplo: /api/v1/subscriptions?sort=+folios |
| per_page | Integer | Opcional | Indica el limite de resultados para mostrar, por default retorna todos las suscripciones del catalogo. Ejemplo: /api/v1/subscriptions?per_page=3 |
| page | Integer | Opcional | Indica número de página a consultar, por default posiciona en la página 1. Ejemplo: /api/v1/subscriptions?page=2 |
Ejemplo de petición
GET /v1/subscriptions HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'GET',
'url': '{ HOST }/v1/subscriptions',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/subscriptions"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-07-22T00:00:00.000000Z",
"folios": 100,
"status": "active",
"client": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]",
"status": "active"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"status": "active"
},
"vigency": "Anual",
"folios_used": 0
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Mostrar suscripción
A continuación se explica la función para consultar una suscripción específica utilizando su UUID. Esta consulta permite obtener la información detallada de la suscripción, incluyendo el plan asociado, vigencia, y estado.
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es GET
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions/UUID de la suscripción
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions/a2154491e9e04adcabf6a051e2dbdaca
Ejemplo de petición
GET /v1/subscriptions/{uuid} HTTP/1.1
Host: {HOST}
Accept: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions/a2154491e9e04adcabf6a051e2dbdaca',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'GET',
'url': '{ HOST }/v1/subscriptions/a2154491e9e04adcabf6a051e2dbdaca',
'headers': {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
url = "{ HOST }/v1/subscriptions/a2154491e9e04adcabf6a051e2dbdaca"
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'F-Sandbox-Mode': 'true'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
require "uri"
require "net/http"
url = URI("{ HOST }/v1/subscriptions/a2154491e9e04adcabf6a051e2dbdaca")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer YOUR_ACCESS_TOKEN"
request["F-Sandbox-Mode"] = "true"
response = http.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a21565b38d6142f38424aa0b351a889e",
"name": "PLAN ELITE",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-07-22T00:00:00.000000Z",
"folios": 100,
"status": "active",
"client": {
"uuid": "a210621b15284f9db98e939008e775db",
"name": "ANA LAURA MARTINEZ",
"email": "[email protected]",
"status": "activo"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"status": "suspended"
},
"vigency": "Anual",
"folios_used": 0
}
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Renovar suscripción
A continuación se explica la función para renovar una suscripción existente y extender la vigencia del plan asignado al cliente. Esta operación permite mantener activa la suscripción aplicando una nueva vigencia sobre el plan actualmente contratado, renovar con un plan distinto.
Estos son los parámetros para renovar una suscripción:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| product_uuid | String | Requerido | UUID del producto o plan que será utilizado para realizar la renovación de la suscripción. |
| vigency_uuid | String | Requerido | UUID de la vigencia que se aplicará al producto seleccionado durante el proceso de renovación de la suscripción. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions/UUID del cliente/renew
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/renew
Ejemplo para renovar suscripción
POST /v1/subscriptions/{uuid}/renew HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"product_uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"vigency_uuid": "a2152b157b4949fab99b1085bd4186b3"
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/renew',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"product_uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"vigency_uuid": "a2152b157b4949fab99b1085bd4186b3"
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/renew',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"product_uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"vigency_uuid": "a2152b157b4949fab99b1085bd4186b3"
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/renew"
payload = json.dumps({
"product_uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"vigency_uuid": "a2152b157b4949fab99b1085bd4186b3"
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/renew")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"product_uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"vigency_uuid": "a2152b157b4949fab99b1085bd4186b3"
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2156965cbc44cf6a9cb3d8934fffd9d",
"name": "PLAN EDITADO",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-09-22T00:00:00.000000Z",
"folios": 50,
"status": null,
"client": {
"uuid": "a210621bcfba4098a0e9ae5e6031f649",
"name": "ANA LAURA MARTINES",
"email": "[email protected]",
"status": "active"
},
"product": {
"uuid": "a2151fa2877f4d0a9781aa3fa275c0d6",
"name": "PLAN EDITADO",
"status": "active"
},
"vigency": "Trimestral",
"folios_used": 0
}
}
{
"status": "error",
"message": "Error de validación de datos.",
"errors": {
"product_uuid": [
"The selected product uuid is invalid."
]
},
"code": "VALIDATION_FAILED"
}
Agregar folios
A continuación se explica la función para agregar folios disponibles a una suscripción. Esta operación permite poner una cantidad específica de folios y registrar el monto asociado al ajuste realizado.
Estos son los parámetros para remover folios:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| folios | Numérico | Requerido | Cantidad de folios que serán agregados de la suscripción. |
| amount | Numérico | Requerido | Monto asociado a la operación de agregar folios. Este valor podrá utilizarse para fines de control o estadísticas. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions/UUID de la suscripción/add-folios
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/add-folios
Ejemplo para agregar folios
POST /v1/subscriptions/{uuid}/add-folios HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"folios": 5,
"amount": 2.99
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/add-folio',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"folios": 5,
"amount": 2.99
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/add-folio',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"folios": 5,
"amount": 2.99
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/add-folio"
payload = json.dumps({
"folios": 5,
"amount": 2.99
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/add-folio")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"folios": 5,
"amount": 2.99
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-07-22T00:00:00.000000Z",
"folios": 105,
"status": "active",
"client": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]",
"status": "active"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"status": "active"
},
"vigency": "Anual",
"folios_used": 0
}
}
{
"status": "error",
"message": "Error de validación de datos.",
"errors": {
"folios": [
"The folios field is required."
]
},
"code": "VALIDATION_FAILED"
}
Retirar folios
A continuación se explica la función para retirar folios disponibles a una suscripción de un cliente. Esta operación permite poner una cantidad específica de folios.
Estos son los parámetros para remover folios:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| folios | Numérico | Requerido | Cantidad de folios que serán agregados de la suscripción. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions/UUID de la suscripción/remove-folios
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/remove-folios
Ejemplo para remover folios
POST /v1/subscriptions/{uuid}/remove-folios HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"folios": 4
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/remove-folios',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"folios": 4
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/remove-folios',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"folios": 4
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/remove-folios"
payload = json.dumps({
"folios": 4
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/subscriptions/a20c4a7f2ab443bf8d548b8713a7ab56/remove-folios")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"folios": 4
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": {
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-07-22T00:00:00.000000Z",
"folios": 101,
"status": "active",
"client": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]",
"status": "active"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"status": "active"
},
"vigency": "Anual",
"folios_used": 0
}
}
{
"status": "error",
"message": "Error de validación de datos.",
"errors": {
"folios": [
"The folios field is required."
]
},
"code": "VALIDATION_FAILED"
}
Suspender suscripción
A continuación se explica la función para suspender una suscripción activa de un cliente. Esta operación permite desactivar temporalmente el plan asignado, deteniendo el acceso a los servicios asociados hasta que la suscripción sea reactivada.
Estos son los parámetros para suspender una suscripción:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| uuids | Array | Requerido | Lista de UUIDs de las suscripciones que serán suspendidas. Permite enviar uno o múltiples registros. |
| uuids[] | String | Requerido | UUID de la suscripción que será suspendida. |
| message | String | Requerido | Mensaje o motivo de la suspensión que será enviado al cliente y registrado en el sistema. |
| keep_folios | Booleano | Requerido | Indica si los folios disponibles de la suscripción deben conservarse después de la suspensión. Valores aceptados: • true → Conserva los folios disponibles.• false → Los folios no se conservan al suspender la suscripción. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions/suspend
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions/suspend
Ejemplo para suspender suscripción
POST /v1/subscriptions/suspend HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"uuids": [
"a2085c1803f9bb39c56227db1daa4de"
],
"message": "prueba por API",
"keep_folios": true
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions/suspend',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"uuids": [
"a2085c1803f9bb39c56227db1daa4de"
],
"message": "prueba por API",
"keep_folios": true
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/subscriptions/suspend',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"uuids": [
"a2085c1803f9bb39c56227db1daa4de"
],
"message": "prueba por API",
"keep_folios": true
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/subscriptions/suspend"
payload = json.dumps({
"uuids": [
"a2085c1803f9bb39c56227db1daa4de"
],
"message": "prueba por API",
"keep_folios": True
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/subscriptions/suspend")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"uuids": [
"a2085c1803f9bb39c56227db1daa4de"
],
"message": "prueba por API",
"keep_folios": true
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": [
{
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-07-22T00:00:00.000000Z",
"folios": 0,
"status": "suspended",
"client": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]",
"status": "active"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"status": "active"
},
"vigency": "Anual",
"folios_used": 0
}
]
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}
Reactivar suscripción
A continuación se explica la función para reactivar una suscripción previamente suspendida. Esta operación permite restaurar el acceso a los servicios del plan asociado al cliente, volviendo a activar su estado operativo.
Estos son los parámetros para reactivar una suscripción:
| Parámetro | Tipo | Requerido | Detalles |
|---|---|---|---|
| uuids | Array | Requerido | Lista de UUIDs de las suscripciones que serán reactivadas. Permite enviar uno o múltiples registros. |
| uuids[] | String | Requerido | UUID de la suscripción que será reactivada. |
Construcción de la URL
Importante
Importante el método para borrar uno o múltiples planes es POST
Host: https://api-partners.factura.com/api
Endpoint: v1/subscriptions/reactivate
Ejemplo: https://api-partners.factura.com/api/v1/subscriptions/reactivate
Ejemplo para reactivar suscripción
POST /v1/subscriptions/reactivate HTTP/1.1
Host: {HOST}
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
F-Sandbox-Mode: true
{
"uuids": [
"a1fe2f3758a54614900a02209b322e9c"
]
}
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => '{ HOST }/v1/subscriptions/reactivate',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"uuids": [
"a1fe2f3758a54614900a02209b322e9c"
]
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: ••••••',
'F-Sandbox-Mode: true'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var request = require('request');
var options = {
'method': 'POST',
'url': '{ HOST }/v1/subscriptions/reactivate',
'headers': {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
},
body: JSON.stringify({
"uuids": [
"a1fe2f3758a54614900a02209b322e9c"
]
})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
import requests
import json
url = "{ HOST }/v1/subscriptions/reactivate"
payload = json.dumps({
"uuids": [
"a1fe2f3758a54614900a02209b322e9c"
]
})
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
'F-Sandbox-Mode': 'true'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
require "uri"
require "json"
require "net/http"
url = URI("{ HOST }/v1/subscriptions/reactivate")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request["F-Sandbox-Mode"] = "true"
request["Authorization"] = "••••••"
request.body = JSON.dump({
"uuids": [
"a1fe2f3758a54614900a02209b322e9c"
]
})
response = https.request(request)
puts response.read_body
Respuesta
{
"response": "success",
"data": [
{
"uuid": "a2154491e9e04adcabf6a051e2dbdaca",
"name": "PLAN ELITE",
"start_date": "2026-06-22T00:00:00.000000Z",
"end_date": "2026-07-22T00:00:00.000000Z",
"folios": 101,
"status": "active",
"client": {
"uuid": "a21544903d574f0c889798f8c13965cc",
"name": "MARTIN LOPEZ EDIT",
"email": "[email protected]",
"status": "active"
},
"product": {
"uuid": "a2106219d0724860a1521780eea0827a",
"name": "PLAN ELITE",
"status": "active"
},
"vigency": "Anual",
"folios_used": 0
}
]
}
{
"status": "error",
"message": "El recurso solicitado no fue encontrado.",
"code": "NOT_FOUND"
}