Registro Completo de Organización
Registra una nueva organización junto con su sucursal principal y opcionalmente su CSD en una sola operación. Este es el endpoint recomendado para el onboarding completo.
Endpoint
POST https://api.lummy.io/v1/organizations/register
| Entorno | URL |
|---|---|
| Producción | https://api.lummy.io/v1/organizations/register |
| Sandbox | https://sandbox.lummy.io/v1/organizations/register |
Este endpoint realiza el onboarding completo en una sola operación:
- Crea la organización
- Crea la sucursal principal (matriz)
- Opcionalmente, sube y valida el CSD si se proporcionan los archivos
Headers
"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...""01936ff8-9c6a-7b2e-8000-123456789abc""multipart/form-data""multipart/form-data"Body Parameters (Multipart)
"Mi Empresa S.A. de C.V.""Mi Empresa Sociedad Anónima de Capital Variable""XAXX010101000""601""64000""Matriz""64000""contraseña_secreta_123""certificado.cer""llave_privada.key"Si decides proporcionar los archivos del CSD, los tres campos csdPassword, cerFile y keyFile son obligatorios. Si no proporcionas ninguno, la organización y sucursal se crearán sin CSD, y podrás subirlo posteriormente usando el endpoint dedicado.
Ejemplos de Código
- cURL
- Node.js (TypeScript)
- Python
- PHP (Guzzle)
Sin CSD:
curl -X POST https://sandbox.lummy.io/organizations/register \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "x-idempotency: $(uuidgen)" \
-F "name=Mi Empresa S.A. de C.V." \
-F "legalName=Mi Empresa S.A. de C.V." \
-F "rfc=XAXX010101000" \
-F "taxRegime=601" \
-F "zipCode=64000" \
-F "branchName=Matriz"
Con CSD:
curl -X POST https://sandbox.lummy.io/organizations/register \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "x-idempotency: $(uuidgen)" \
-F "name=Mi Empresa S.A. de C.V." \
-F "legalName=Mi Empresa S.A. de C.V." \
-F "rfc=XAXX010101000" \
-F "taxRegime=601" \
-F "zipCode=64000" \
-F "branchName=Matriz" \
-F "csdPassword=contraseña_csd" \
-F "cerFile=@/path/to/certificado.cer" \
-F "keyFile=@/path/to/llave.key"
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';
import { v4 as uuidv4 } from 'uuid';
interface RegisterOrganizationResponse {
organizationId: string;
branchId: string;
csdId?: string;
message: string;
}
async function registroCompleto(includeCsd: boolean = false): Promise<RegisterOrganizationResponse> {
const API_URL = 'https://sandbox.lummy.io/organizations/register';
const ACCESS_TOKEN = process.env.ACCESS_TOKEN!;
const form = new FormData();
form.append('name', 'Mi Empresa S.A. de C.V.');
form.append('legalName', 'Mi Empresa S.A. de C.V.');
form.append('rfc', 'XAXX010101000');
form.append('taxRegime', '601');
form.append('zipCode', '64000');
form.append('branchName', 'Matriz');
if (includeCsd) {
form.append('csdPassword', 'contraseña_csd');
form.append('cerFile', fs.createReadStream('./certificado.cer'));
form.append('keyFile', fs.createReadStream('./llave.key'));
}
try {
const response = await axios.post<RegisterOrganizationResponse>(API_URL, form, {
headers: {
...form.getHeaders(),
'Authorization': `Bearer ${ACCESS_TOKEN}`,
'x-idempotency': uuidv4(),
},
});
console.log('Organizacion registrada exitosamente');
console.log('Organization ID:', response.data.organizationId);
console.log('Branch ID:', response.data.branchId);
if (response.data.csdId) {
console.log('CSD ID:', response.data.csdId);
}
return response.data;
} catch (error) {
console.error('Error en registro:', error);
throw error;
}
}
// Ejecutar
registroCompleto(false); // Sin CSD
// registroCompleto(true); // Con CSD
npm install axios form-data uuid
npm install -D @types/uuid @types/node
import os
import requests
from uuid import uuid4
def registro_completo(include_csd=False):
api_url = "https://sandbox.lummy.io/organizations/register"
access_token = os.getenv("ACCESS_TOKEN")
if not access_token:
raise ValueError("Debes definir ACCESS_TOKEN")
headers = {
"Authorization": f"Bearer {access_token}",
"x-idempotency": str(uuid4()),
}
data = {
'name': 'Mi Empresa S.A. de C.V.',
'legalName': 'Mi Empresa S.A. de C.V.',
'rfc': 'XAXX010101000',
'taxRegime': '601',
'zipCode': '64000',
'branchName': 'Matriz'
}
files = None
if include_csd:
data['csdPassword'] = 'contraseña_csd'
files = {
'cerFile': ('certificado.cer', open('./certificado.cer', 'rb')),
'keyFile': ('llave.key', open('./llave.key', 'rb'))
}
try:
response = requests.post(api_url, data=data, files=files, headers=headers, timeout=60)
response.raise_for_status()
result = response.json()
print("Organizacion registrada exitosamente")
print(f"Organization ID: {result['organizationId']}")
print(f"Branch ID: {result['branchId']}")
if result.get('csdId'):
print(f"CSD ID: {result['csdId']}")
return result
except requests.exceptions.RequestException as e:
print(f"Error en registro: {e}")
if e.response:
print(f"Detalle: {e.response.text}")
raise
finally:
if files:
files['cerFile'][1].close()
files['keyFile'][1].close()
if __name__ == "__main__":
registro_completo(include_csd=False) # Sin CSD
# registro_completo(include_csd=True) # Con CSD
pip install requests
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Ramsey\Uuid\Uuid;
function registroCompleto($includeCsd = false)
{
$apiUrl = 'https://sandbox.lummy.io/organizations/register';
$accessToken = getenv('ACCESS_TOKEN');
if (!$accessToken) {
throw new Exception('Debes definir ACCESS_TOKEN');
}
$client = new Client(['timeout' => 60]);
$multipart = [
['name' => 'name', 'contents' => 'Mi Empresa S.A. de C.V.'],
['name' => 'legalName', 'contents' => 'Mi Empresa S.A. de C.V.'],
['name' => 'rfc', 'contents' => 'XAXX010101000'],
['name' => 'taxRegime', 'contents' => '601'],
['name' => 'zipCode', 'contents' => '64000'],
['name' => 'branchName', 'contents' => 'Matriz'],
];
if ($includeCsd) {
$multipart[] = ['name' => 'csdPassword', 'contents' => 'contraseña_csd'];
$multipart[] = [
'name' => 'cerFile',
'contents' => fopen('./certificado.cer', 'r'),
'filename' => 'certificado.cer'
];
$multipart[] = [
'name' => 'keyFile',
'contents' => fopen('./llave.key', 'r'),
'filename' => 'llave.key'
];
}
try {
$response = $client->post($apiUrl, [
'headers' => [
'Authorization' => 'Bearer ' . $accessToken,
'x-idempotency' => Uuid::uuid4()->toString(),
],
'multipart' => $multipart
]);
$data = json_decode($response->getBody(), true);
echo "Organizacion registrada exitosamente\n";
echo "Organization ID: " . $data['organizationId'] . "\n";
echo "Branch ID: " . $data['branchId'] . "\n";
if (isset($data['csdId'])) {
echo "CSD ID: " . $data['csdId'] . "\n";
}
return $data;
} catch (RequestException $e) {
echo "Error en registro: " . $e->getMessage() . "\n";
if ($e->getResponse()) {
echo "Detalle: " . $e->getResponse()->getBody() . "\n";
}
throw $e;
}
}
try {
registroCompleto(false); // Sin CSD
// registroCompleto(true); // Con CSD
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
exit(1);
}
composer require guzzlehttp/guzzle ramsey/uuid
Respuestas
Todas las respuestas siguen el formato estándar StandardResponse.
201 Created
Organización registrada exitosamente.
{
"requestId": "abc123-def456",
"data": {
"organizationId": "550e8400-e29b-41d4-a716-446655440000",
"branchId": "550e8400-e29b-41d4-a716-446655440001",
"csdId": "550e8400-e29b-41d4-a716-446655440002",
"message": "Organización registrada exitosamente"
},
"timestamp": "2025-01-15T10:30:00.000Z",
"path": "/organizations/register",
"method": "POST"
}
Si no se proporcionaron archivos CSD, el campo csdId será null.
400 Bad Request
Datos inválidos o archivos CSD incorrectos.
{
"requestId": "abc123-def456",
"error": {
"message": "El RFC del certificado no coincide con el RFC de la organización",
"code": "ValidationError",
"status": 400
},
"timestamp": "2025-01-15T10:30:00.000Z",
"path": "/organizations/register",
"method": "POST"
}
409 Conflict
Ya existe una organización con el mismo RFC.
{
"requestId": "abc123-def456",
"error": {
"message": "Ya existe una organización con el RFC: XAXX010101000",
"code": "ConflictException",
"status": 409
},
"timestamp": "2025-01-15T10:30:00.000Z",
"path": "/organizations/register",
"method": "POST"
}
Ventajas
Este endpoint combina tres operaciones en una:
- POST
/organizations- Crear organización - POST
/branches- Crear sucursal principal - POST
/branches/:id/csd- Subir CSD (opcional)
Beneficios:
- Menos llamadas a la API
- Operación atómica (todo o nada)
- Idempotencia garantizada con un solo UUID
- Onboarding más rápido