Actualizar CSD
Actualiza el Certificado de Sello Digital (CSD) de una sucursal. Esto reemplaza el CSD activo por uno nuevo.
Endpoint
PUT https://api.lummy.io/v1/branches/{id}/csd
| Entorno | URL |
|---|---|
| Producción | https://api.lummy.io/v1/branches/{id}/csd |
| Sandbox | https://sandbox.lummy.io/v1/branches/{id}/csd |
Path Parameters
{
"id": stringrequerido
↳Identificador único de la sucursal. Debe ser un UUID válido de una sucursal que pertenezca a la organización especificada en el header.
↳Formato: uuid
}
Headers
{
"Authorization": string,requerido
↳Token de autenticación en formato Bearer. Se obtiene del endpoint de autenticación y debe incluirse en todas las peticiones para verificar la identidad del usuario.
"x-organization-id": string,requerido
↳Identificador único de la organización. Debe ser un UUID válido de una organización a la que el usuario autenticado tenga acceso.
↳Formato: uuid
"x-idempotency": string,requerido
↳Clave de idempotencia única para esta operación. Debe ser un UUID generado por el cliente. Si se envía la misma clave dos veces, la segunda petición retornará el resultado de la primera sin procesarla nuevamente.
↳Formato: uuid
"Content-Type": stringrequerido
↳Tipo de contenido de la petición. Debe ser multipart/form-data para permitir la carga de archivos.
↳Valores permitidos:
"multipart/form-data"}
Body Parameters (Multipart)
{
"cerFile": string,requerido
↳Archivo del certificado de sello digital emitido por el SAT. Archivo .cer que contiene la llave pública para firmar CFDIs. Este archivo es proporcionado por el SAT al tramitar el CSD y tiene una vigencia de 4 años.
↳Formato: binary
"keyFile": string,requerido
↳Archivo de la llave privada del certificado de sello digital emitido por el SAT. Archivo .key cifrado que contiene la llave privada para firmar CFDIs. Este archivo debe protegerse con una contraseña al momento de su descarga desde el SAT.
↳Formato: binary
"password": stringrequerido
↳Contraseña de la llave privada del CSD. Es la contraseña que se configuró al momento de descargar el archivo .key desde el portal del SAT. Esta contraseña es necesaria para descifrar y utilizar la llave privada en el proceso de sellado de CFDIs.
}
Ejemplos de Código
- cURL
- Node.js (TypeScript)
- Python
- PHP (Guzzle)
curl -X PUT https://sandbox.lummy.io/branches/${BRANCH_ID}/csd \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "x-organization-id: ${LUMMY_ORG_ID}" \
-H "x-idempotency: $(uuidgen)" \
-F "cerFile=@/path/to/nuevo_certificado.cer" \
-F "keyFile=@/path/to/nueva_llave.key" \
-F "password=nueva_contrasena_csd"
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';
import { v4 as uuidv4 } from 'uuid';
interface CsdResponse {
id: string;
serialNumber: string;
validFrom: string;
validTo: string;
status: string;
}
async function actualizarCsd(branchId: string): Promise<CsdResponse> {
const ORG_ID = process.env.LUMMY_ORG_ID!;
const API_URL = `https://sandbox.lummy.io/branches/${branchId}/csd`;
const ACCESS_TOKEN = process.env.ACCESS_TOKEN!;
const form = new FormData();
form.append('cerFile', fs.createReadStream('./nuevo_certificado.cer'));
form.append('keyFile', fs.createReadStream('./nueva_llave.key'));
form.append('password', 'nueva_contrasena_csd');
const response = await axios.put<CsdResponse>(API_URL, form, {
headers: {
...form.getHeaders(),
'Authorization': `Bearer ${ACCESS_TOKEN}`,
'x-organization-id': ORG_ID,
'x-idempotency': uuidv4(),
},
});
console.log('CSD actualizado exitosamente');
console.log('ID:', response.data.id);
return response.data;
}
actualizarCsd('your-branch-uuid');
import os
import requests
from uuid import uuid4
def actualizar_csd(branch_id):
org_id = os.getenv("LUMMY_ORG_ID")
api_url = f"https://sandbox.lummy.io/branches/{branch_id}/csd"
access_token = os.getenv("ACCESS_TOKEN")
headers = {
"Authorization": f"Bearer {access_token}",
"x-organization-id": org_id,
"x-idempotency": str(uuid4()),
}
files = {
'cerFile': ('nuevo_certificado.cer', open('./nuevo_certificado.cer', 'rb')),
'keyFile': ('nueva_llave.key', open('./nueva_llave.key', 'rb'))
}
data = {
'password': 'nueva_contrasena_csd'
}
try:
response = requests.put(api_url, files=files, data=data, headers=headers, timeout=60)
response.raise_for_status()
result = response.json()
print("CSD actualizado exitosamente")
print(f"ID: {result['id']}")
return result
finally:
files['cerFile'][1].close()
files['keyFile'][1].close()
if __name__ == "__main__":
actualizar_csd("your-branch-uuid")
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use Ramsey\Uuid\Uuid;
function actualizarCsd(string $branchId): array
{
$orgId = getenv('LUMMY_ORG_ID');
$apiUrl = "https://sandbox.lummy.io/branches/{$branchId}/csd";
$accessToken = getenv('ACCESS_TOKEN');
$client = new Client(['timeout' => 60]);
$response = $client->put($apiUrl, [
'headers' => [
'Authorization' => 'Bearer ' . $accessToken,
'x-organization-id' => $orgId,
'x-idempotency' => Uuid::uuid4()->toString(),
],
'multipart' => [
[
'name' => 'password',
'contents' => 'nueva_contrasena_csd'
],
[
'name' => 'cerFile',
'contents' => fopen('./nuevo_certificado.cer', 'r'),
'filename' => 'nuevo_certificado.cer'
],
[
'name' => 'keyFile',
'contents' => fopen('./nueva_llave.key', 'r'),
'filename' => 'nueva_llave.key'
],
]
]);
$data = json_decode($response->getBody(), true);
echo "CSD actualizado exitosamente\n";
echo "ID: " . $data['id'] . "\n";
return $data;
}
actualizarCsd('your-branch-uuid');
Respuestas
Todas las respuestas siguen el formato estándar StandardResponse.
200 OK
CSD actualizado y validado exitosamente.
{
"type": ,opcional
"properties": opcional
}
{
"requestId": "abc123-def456",
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"serialNumber": "00001000000123456789",
"validFrom": "2024-01-01T00:00:00.000Z",
"validTo": "2028-01-01T00:00:00.000Z",
"status": "active"
},
"timestamp": "2025-01-15T10:30:00.000Z",
"path": "/branches/789e8400-e29b-41d4-a716-446655449999/csd",
"method": "PUT"
}
400 Bad Request
- Archivos faltantes.
- Contraseña incorrecta.
- El RFC del certificado no coincide con el RFC de la organización.
- Certificado caducado o revocado.
{
"requestId": "abc123-def456",
"error": {
"message": "Contraseña incorrecta para el archivo .key",
"code": "ValidationError",
"status": 400
},
"timestamp": "2025-01-15T10:30:00.000Z",
"path": "/branches/789e8400-e29b-41d4-a716-446655449999/csd",
"method": "PUT"
}
404 Not Found
La sucursal especificada no existe.
{
"requestId": "abc123-def456",
"error": {
"message": "Branch not found",
"code": "NotFoundException",
"status": 404
},
"timestamp": "2025-01-15T10:30:00.000Z",
"path": "/branches/789e8400-e29b-41d4-a716-446655449999/csd",
"method": "PUT"
}