POST /credentials/issue
Emite credenciales a uno o multiples recipientes.
- 1 recipiente: Emision sincrona. Retorna la credencial inmediatamente.
- 2+ recipientes: Emision asincrona. Retorna un
job_idpara consultar el progreso.
Request
POST /api/v1/credentials/issue
Headers
| Header | Requerido | Descripcion |
|---|---|---|
X-API-Key | Si | Tu API key |
Content-Type | Si | application/json |
Body
{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"recipients": [
{
"email": "estudiante@ejemplo.com",
"recipient_name": "Juan Perez",
"result_value": "A",
"credits_earned": 6.0
}
]
}
Campos del recipiente
| Campo | Tipo | Requerido | Descripcion |
|---|---|---|---|
email | string | Siempre | Email del recipiente |
recipient_name | string | Segun template | Nombre completo |
result_value | string | Segun template | Calificacion/resultado |
credits_earned | number | Segun template | Creditos obtenidos |
evidence | array | Segun template | Evidencia del trabajo |
role | string | Segun template | Rol del recipiente |
license_number | string | Segun template | Numero de licencia |
term | string | Segun template | Periodo academico |
activity_start_date | string | Segun template | Fecha inicio (YYYY-MM-DD) |
activity_end_date | string | Segun template | Fecha fin (YYYY-MM-DD) |
Estructura de evidence
{
"evidence": [
{
"name": "Proyecto Final",
"url": "https://ejemplo.com/proyecto",
"description": "Implementacion de API REST en Python"
}
]
}
Consulta GET /templates/\{id\} para saber que campos son requeridos por cada template.
Response: Emision sincrona (1 recipiente)
{
"mode": "sync",
"credentials": [
{
"email": "estudiante@ejemplo.com",
"status": "issued",
"credential_id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"credential_url": "https://app.unicreda.com/credential/7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d"
}
]
}
Response: Emision asincrona (2+ recipientes)
{
"mode": "async",
"job_id": "abc123-task-id",
"message": "Issuing 50 credentials in background. Poll GET /api/v1/jobs/abc123-task-id for status."
}
Usa GET /jobs/\{job_id\} para consultar el progreso.
Deteccion automatica interno/externo
La API detecta automaticamente si el email corresponde a un miembro de tu organizacion:
- Interno: Se enlazan automaticamente al wallet del usuario + se auto-llenan campos del perfil
- Externo: Se crea la credencial y se envia por email con un enlace publico
Errores por recipiente
Si un recipiente tiene datos invalidos en modo sincrono:
{
"mode": "sync",
"credentials": [
{
"email": "estudiante@ejemplo.com",
"status": "error",
"errors": ["Calificacion invalida. Valores permitidos: A, B, C, D, F"]
}
]
}
Ejemplo: Emision masiva con Python
import requests
import time
API_KEY = "uc_live_tu_key_aqui"
BASE_URL = "https://app.unicreda.com/api/v1"
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
# Emitir a multiples recipientes
response = requests.post(f"{BASE_URL}/credentials/issue", headers=headers, json={
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"recipients": [
{"email": f"estudiante{i}@ejemplo.com", "recipient_name": f"Estudiante {i}", "result_value": "A"}
for i in range(1, 51)
]
})
data = response.json()
if data["mode"] == "async":
job_id = data["job_id"]
# Polling del progreso
while True:
status = requests.get(f"{BASE_URL}/jobs/{job_id}", headers=headers).json()
print(f"Status: {status['status']}")
if status["status"] == "SUCCESS":
print(f"Resultado: {status['result']}")
break
elif status["status"] == "FAILURE":
print(f"Error: {status['error']}")
break
time.sleep(2) # Esperar 2 segundos entre consultas