API JSON-RPC del TIR
Todos los métodos se invocan mediante POST /trusted-issuers-registry/v1/jsonrpc con el header x-api-key: <API_KEY>.
Tipos de datos
IssuerType
El campo issuerType acepta los siguientes valores de cadena (no los valores numéricos):
| Nombre | Valor numérico | Descripción |
|---|---|---|
NONE | 0 | Sin rol asignado. No se usa directamente en publicaciones. |
ROOT_TAO | 1 | Root Trusted Accreditation Organisation. Solo ISBE puede usarlo. |
TAO | 2 | Trusted Accreditation Organisation. |
TI | 3 | Trusted Issuer. |
REVOKED | 4 | Acreditación revocada. Usar para revocar un atributo existente. |
Dirección Ethereum (address)
Cadena hexadecimal con prefijo 0x de 40 caracteres: 0x8445fC96e27ceB0d1794be16a1Ac8BF5D765AACB.
Cadena hexadecimal (hexstring)
Cadena con prefijo 0x seguida de caracteres hexadecimales: 0x3f4143c6f3a1c79b....
DID
Cadena con el prefijo did:isbe:uc: o did:isbe:uc-pre: según el entorno, seguida del identificador del DID.
setAttributeMetadata
Construye una transacción no firmada que registra los metadatos del rol de un emisor en el contrato TIR. La transacción resultante debe ser firmada por el propietario de la clave asociada al campo from y enviada con sendSignedTransaction.
Petición
{
"jsonrpc": "2.0",
"method": "setAttributeMetadata",
"params": [
{
"from": "0x8445fC96e27ceB0d1794be16a1Ac8BF5D765AACB",
"did": "did:isbe:uc:zpxbBfHYA5GN45rS1tSEBJg",
"revisionId": "0x3f4143c6f3a1c79bb32f45a6cbd90ee6bb2e2e71eadda99e371a4a144c53050f",
"issuerType": "TI",
"taoDid": "did:isbe:uc:zj4sk7oEMx1SGNAzibWxVAV",
"attributeIdTao": "0xbd6123874c340eaea25a1fc01785593c350fd9216ed3a69864549f8013d501b4"
}
],
"id": 1
}
Parámetros
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
from | address | ✅ | Dirección Ethereum de quien firma la transacción. |
did | did | ✅ | DID del sujeto al que se asigna el rol. |
revisionId | hexstring | ✅ | Identificador del atributo en el TIR. Debe coincidir con el reservedAttributeId de la acreditación. 64 hex chars + prefijo 0x. |
issuerType | IssuerType | ✅ | Rol a registrar: ROOT_TAO, TAO, TI o REVOKED. |
taoDid | did | ✅ | DID de la TAO (o RTAO) que acredita al sujeto. Para la revocación, introduce el mismo valor que en la publicación original. |
attributeIdTao | hexstring | ✅ | attributeId de la acreditación de la TAO padre en el TIR (prefijado con 0x). |
Respuesta exitosa
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"from": "0x8445fC96e27ceB0d1794be16a1Ac8BF5D765AACB",
"to": "0x00000000000000000000000000000000000015Be",
"data": "0x250f4d97...",
"value": "0x0",
"nonce": "0xb1d3",
"chainId": "0x...",
"gasLimit": "0x1000000",
"gasPrice": "0x0"
}
}
El result es una transacción no firmada. El campo to es la dirección del contrato TIR.
Errores frecuentes
| Código | Causa |
|---|---|
-32600 | API Key inválida o faltante. |
-32602 | Parámetro faltante, dirección Ethereum inválida, DID con formato incorrecto, issuerType desconocido. |
setAttributeData
Construye una transacción no firmada que almacena el JWT completo de la acreditación (codificado en hexadecimal) en el contrato TIR. Debe ejecutarse después de setAttributeMetadata para el mismo atributo.
Petición
{
"jsonrpc": "2.0",
"method": "setAttributeData",
"params": [
{
"from": "0xD442e39AAd178Ec9DfD039aD048203D5d0122e61",
"did": "did:isbe:uc:zpxbBfHYA5GN45rS1tSEBJg",
"attributeId": "0x3f4143c6f3a1c79bb32f45a6cbd90ee6bb2e2e71eadda99e371a4a144c53050f",
"attributeData": "0x65794a6862476369..."
}
],
"id": 2
}
Parámetros
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
from | address | ✅ | Dirección Ethereum de quien firma la transacción. |
did | did | ✅ | DID del sujeto al que pertenece el atributo. |
attributeId | hexstring | ✅ | Mismo revisionId usado en setAttributeMetadata para este atributo. |
attributeData | hexstring | ✅ | JWT de la acreditación codificado como cadena hexadecimal con prefijo 0x. Para convertir: "0x" + Buffer.from(jwt_string).toString("hex"). |
Codificación de attributeData
El JWT generado por el CLI debe convertirse a hexadecimal antes de enviarlo. En Node.js:
const jwt = "eyJhbGciOiJFUzI1NiIs...";
const attributeData = "0x" + Buffer.from(jwt, "utf8").toString("hex");
Respuesta exitosa
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"from": "0xD442e39AAd178Ec9DfD039aD048203D5d0122e61",
"to": "0x00000000000000000000000000000000000015Be",
"data": "0x...",
"value": "0x0",
"nonce": "0xb1d4",
"chainId": "0x...",
"gasLimit": "0x1000000",
"gasPrice": "0x0"
}
}
sendSignedTransaction
Envía una transacción ya firmada a la blockchain ISBE y devuelve el hash de la transacción. Úsalo para enviar cada una de las transacciones no firmadas obtenidas con setAttributeMetadata y setAttributeData.
sendSignedTransaction devuelve el hash en cuanto la transacción entra en la mempool. No garantiza que haya sido incluida en un bloque ni que haya tenido éxito. Debes consultar el recibo con eth_getTransactionReceipt y verificar que status = 0x1.
Petición
{
"jsonrpc": "2.0",
"method": "sendSignedTransaction",
"params": [
{
"protocol": "eth",
"unsignedTransaction": {
"from": "0x8445fC96e27ceB0d1794be16a1Ac8BF5D765AACB",
"to": "0x00000000000000000000000000000000000015Be",
"data": "0x250f4d97...",
"nonce": "0xb1d3",
"chainId": "0x...",
"gasLimit": "0x1000000",
"gasPrice": "0x0",
"value": "0x0"
},
"r": "0xf5649febb203...",
"s": "0x22d5188b34c3...",
"v": "0x1B",
"signedRawTransaction": "0xf9014c..."
}
],
"id": 3
}
Parámetros
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
protocol | string | ✅ | Siempre "eth". |
unsignedTransaction | object | ✅ | Objeto de transacción no firmada exactamente como lo devolvió setAttributeMetadata o setAttributeData. |
unsignedTransaction.from | address | ✅ | Dirección Ethereum del firmante. Debe coincidir con el firmante real de la transacción. |
unsignedTransaction.to | address | ✅ | Dirección del contrato TIR. |
unsignedTransaction.data | hexstring | ✅ | Payload de la transacción (campo data del resultado de setAttributeMetadata/setAttributeData). |
unsignedTransaction.nonce | hexstring | ✅ | Nonce de la transacción. |
unsignedTransaction.chainId | hexstring | ✅ | Chain ID de la red ISBE. |
unsignedTransaction.gasLimit | hexstring | ✅ | Gas limit. |
unsignedTransaction.gasPrice | hexstring | ✅ | Gas price (normalmente "0x0" en ISBE). |
unsignedTransaction.value | hexstring | ✅ | Valor en wei ("0x0"). |
r | hexstring | ✅ | Componente r de la firma ECDSA. |
s | hexstring | ✅ | Componente s de la firma ECDSA. |
v | hexstring | ✅ | Componente v de la firma ECDSA. |
signedRawTransaction | hexstring | ✅ | Transacción completa serializada y firmada. |
Validaciones del servidor
El servidor verifica que:
signedRawTransactiones coherente conunsignedTransaction + (r, s, v).- El firmante recuperado de la firma coincide con
unsignedTransaction.from. - El
chainIdde la transacción coincide con el de la red del servidor. - El campo
toapunta al contrato TIR configurado en el servidor.
Si cualquiera de estas validaciones falla, el servidor devuelve -32602 sin enviar la transacción a la blockchain.
Respuesta exitosa
{
"jsonrpc": "2.0",
"id": 3,
"result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
}
El result es el hash de la transacción. Úsalo para consultar el recibo.
Consultar el recibo de la transacción
Consulta el endpoint de Besu con el método eth_getTransactionReceipt:
curl -X POST <besu-rpc-url> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": ["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"],
"id": 1
}'
Campos relevantes del recibo:
status:"0x1"= éxito,"0x0"= fallo.revertReason: motivo del fallo (sistatus = 0x0).
Endpoint REST: leer una acreditación
GET <base-url>/v1/issuers/{did}/attributes/{attributeId}
Autenticación: ninguna.
Parámetros de path:
| Parámetro | Descripción |
|---|---|
did | DID del sujeto de la acreditación. |
attributeId | Identificador del atributo en el TIR. Sin prefijo 0x. |
Respuesta 200 OK:
{
"did": "did:isbe:uc:zpxbBfHYA5GN45rS1tSEBJg",
"attribute": {
"body": "eyJhbGciOiJFUzI1NiIs...",
"hash": "3f4143c6f3a1c79bb32f45a6cbd90ee6bb2e2e71eadda99e371a4a144c53050f",
"issuerType": "TI",
"rootTao": "did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV",
"tao": "did:isbe:uc:zj4sk7oEMx1SGNAzibWxVAV"
}
}
| Campo | Descripción |
|---|---|
did | DID del sujeto. |
attribute.body | JWT de la acreditación (Base64url). |
attribute.hash | Hash del atributo en el TIR (sin prefijo 0x). Coincide con el attributeId. |
attribute.issuerType | Tipo de rol: RTAO, TAO, TI o REVOKED. |
attribute.rootTao | DID de la RTAO raíz de la cadena. |
attribute.tao | DID de la TAO inmediatamente superior. |
Errores:
| Código | Causa |
|---|---|
404 Not Found | El DID o el attributeId no existen en el TIR. |
400 Bad Request | El attributeId contiene caracteres no hexadecimales. |
Endpoint de salud
GET /health
Autenticación: ninguna.
Respuesta 200 OK:
{
"status": "ok",
"uptime": 12.34
}
Endpoint de métricas
GET /metrics
Expone métricas en formato Prometheus para monitorización con Grafana.
Autenticación: ninguna.