Subir CSD
POSThttps://api.cfdi.express/v1/merchants/{id}/csdAPI key
Sube el CSD del emisor (.cer y .key en base64 más la contraseña). Se valida, se encripta y se registra con el PAC.
Antes de tocar al PAC validamos localmente: que el .cer sea legible, que esté vigente, que la llave corresponda al certificado, que la contraseña abra la llave y que no estés subiendo una FIEL en lugar de un CSD.
Los archivos se guardan con encriptación de sobre AES-256-GCM. La llave privada nunca se devuelve por la API.
Autenticación
Authorization: Bearer sk_test_... | sk_live_...Parámetros
Parámetros de ruta
| Campo | Tipo | Descripción |
|---|---|---|
| idreq | string | Id del emisor. |
Cuerpo (JSON)
| Campo | Tipo | Descripción |
|---|---|---|
| cerreq | string | Archivo .cer (DER) codificado en base64. |
| keyreq | string | Archivo .key (DER, PKCS#8 encriptado) en base64. |
| passwordreq | string | Contraseña de la llave privada. |
Ejemplos
cURL
curl -X POST https://api.cfdi.express/v1/merchants/mkq2f8v3x1t7p9d4n6c0b5rz/csd \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d "{
\"cer\": \"$(base64 -w0 CSD_EKU9003173C9.cer)\",
\"key\": \"$(base64 -w0 CSD_EKU9003173C9.key)\",
\"password\": \"12345678a\"
}"Node.js
import { readFile } from "node:fs/promises";
const [cer, key] = await Promise.all([
readFile("CSD_EKU9003173C9.cer"),
readFile("CSD_EKU9003173C9.key"),
]);
const res = await fetch(
`https://api.cfdi.express/v1/merchants/${merchantId}/csd`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CFDI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
cer: cer.toString("base64"),
key: key.toString("base64"),
password: "12345678a",
}),
},
);
const csd = await res.json();
console.log("Vigente hasta", csd.validTo);Respuesta
201 Created
{
"object": "csd",
"serialNumber": "30001000000500003416",
"rfc": "EKU9003173C9",
"validFrom": "2023-05-18T00:00:00.000Z",
"validTo": "2027-05-18T00:00:00.000Z",
"status": "active",
"registeredWithPac": true,
"updatedAt": "2026-08-18T16:24:51.002Z"
}400 — CSD inválido
{
"type": "https://api.cfdi.express/docs/errors/validation_error",
"title": "Validation error",
"status": 400,
"code": "validation_error",
"detail": "The private key could not be opened with the given password",
"subcode": "csd_key_unreadable"
}Errores
| Status | code | Cuándo aparece |
|---|---|---|
| 400 | validation_error | El subcode identifica el problema: csd_invalid_cer, csd_expired, csd_not_yet_valid, csd_key_unreadable, csd_key_mismatch, csd_is_fiel o csd_rejected_by_pac. |
| 401 | unauthorized | Falta el header Authorization o la llave es inválida. |
| 404 | not_found | El emisor no existe en tu cuenta. |
| 503 | pac_unavailable | El PAC no está disponible para registrar el certificado. |
Notas
- El RFC del certificado debe coincidir con el RFC del emisor.
- Un CSD vencido no se puede subir. Renuévalo en el portal del SAT y usa PUT /v1/merchants/{id}/csd.
