API para terceros

Tu sistema puede consultar un código de usuario de LOOKLOCK CHAT y enviarle un mensaje cifrado, sin que LOOKLOCK CHAT pueda leerlo.

Ciframos nosotros: no. Cifras tú.

La clave privada de cada usuario vive solo en su teléfono. Nuestros servidores no la tienen y no pueden tenerla, así que no podemos cifrar un mensaje por ti: si pudiéramos, tendríamos el texto en claro y todo lo que promete LOOKLOCK CHAT se cae.

Lo que hace tu sistema es pedirnos la clave pública del destinatario y cifrar él, en su propia máquina. A nosotros llega un sobre cerrado que solo el destinatario puede abrir. Más abajo está la receta completa y una implementación de referencia que funciona.

Dicho sin rodeos: integrarse cuesta más que con una API que cifra por ti. Ese es el precio de que nadie más pueda leer los mensajes, y no hay forma de rebajarlo sin romper la promesa.

Quién puede usarla

Empresas verificadas. Hacen falta datos de facturación —razón social, NIF o VAT, dirección y correo de administración— y una persona de LOOKLOCK CHAT los revisa antes de activar el acceso. No es un trámite automático a propósito: una clave de API puede escribir a nuestros usuarios, y queremos saber quién la tiene.

Mientras la verificación está en curso, el acceso responde con el código empresa_no_verificada.

Planes

El plan lo determina el número de llamadas al mes. Hay dos gratuitos y no son lo mismo: Prueba son unas consultas para ver si la API te sirve, antes de estar verificada; Freemium es gratis de forma permanente, con cupo mensual, para empresas ya verificadas.

Plan Cupo Puede Precio
Prueba 10 consultas en total solo consultar consultar
Freemium 100 llamadas al mes solo consultar consultar
Inicial 10.000 llamadas al mes consultar y enviar consultar
Profesional 100.000 llamadas al mes consultar y enviar consultar
Corporativo 1.000.000 llamadas al mes consultar y enviar consultar
A medida a convenir consultar y enviar consultar

Los planes gratuitos solo consultan. Enviar mensajes gratis a códigos de usuario ajenos sería un buzón de correo basura regalado, y quien lo recibe no podría saber que quien le escribe no ha verificado nada.

Solicitar acceso

Autenticación

Una cabecera en cada petición, con el identificador de la clave y su secreto separados por un punto:

Authorization: Bearer llk_live_a1b2c3d4e5f6g7h8.<secreto>

El identificador es público y aparece en los registros. El secreto se muestra una sola vez, al crear la clave: en nuestra base solo queda su huella, así que no podemos recuperarlo ni nosotros. Si se pierde, se revoca esa clave y se emite otra.

Las claves de llk_test_ son de pruebas y las de llk_live_ de producción. Se separan para que un fallo en tu entorno de pruebas no mande mensajes reales a nadie.

La base es https://looklock.chat/api/v1/socios/ y todo va por HTTPS.

Los endpoints

GET/cuenta

Tu plan, tus ámbitos y lo que te queda de cupo. No gasta cupo: preguntar cuánto te queda no puede costarte una llamada. Es lo primero que conviene llamar al integrarse.

{ "blnSuccess": true, "data": { "strRazonSocial": "ACME SL", "strPlan": "inicial", "strEntorno": "produccion", "arrAmbitos": ["usuarios:leer", "mensajes:enviar"], "arrCupo": { "strTipo": "mensual", "intCupo": 10000, "intUsado": 15, "intRestante": 9985 }, "strPeriodo": "2026-09" } }
GET/usuarios/{codigo}

Los datos públicos de un código de usuario y su clave pública, que es lo que necesitas para cifrarle. Requiere el ámbito usuarios:leer.

{ "blnSuccess": true, "data": { "strUserCode": "MPRTRMPR", "strNick": "alguien", "blnPhoneVerified": true, "strNodeUrl": "", "strPublicKey": "BBOEs0FmF...", // 65 bytes en base64 "strCifrado": "ECIES-v2" } }

Nunca devolvemos el correo, el teléfono ni los apellidos de nadie: un código de usuario es una identidad pública, un correo no lo es. Y un código que no existe y uno que existe pero aún no puede recibir mensajes dan el mismo 404, para que esto no sirva como detector de códigos válidos.

POST/mensajes

Entrega un mensaje ya cifrado. Requiere el ámbito mensajes:enviar.

{ "strDestinatario": "MPRTRMPR", "strContenidoCifrado": "eyJ2IjoyLCJjdCI6...", // el sobre, ver abajo "strIdCliente": "tu-referencia-001", // opcional, para cuadrarlo "intPrioridad": 0 // 1 = urgente }

El primer mensaje a alguien no llega como una conversación abierta: llega como una propuesta. La persona ve quién le escribe y decide si acepta. Es el mismo mecanismo que entre dos personas, y significa que una clave de API no es permiso para escribir a cualquiera. Tu sistema aparece con su nombre y su propio código de usuario, y puede ser bloqueado como cualquier otro.

GET/mensajes/{id}

El estado de un mensaje tuyo: en_el_buzon, entregado o leido. Solo de los tuyos.

Cómo se construye el sobre (ECIES v2)

Seis pasos. No hay atajos: el sobre que no cumpla esto exactamente no lo podrá abrir el destinatario.

1Genera una pareja de claves efímera en la curva prime256v1 (P-256 / secp256r1). Una por mensaje.
2Z = secreto ECDH con la clave pública del destinatario, como los 32 bytes de la coordenada X en big-endian. Siempre 32, rellenando con ceros por delante si hace falta.
3clave = HKDF-SHA256 con ikm=Z, salt=epk, info="LOOKLOCK-v2", 32 bytes. La epk son los 65 bytes de tu clave pública efímera sin comprimir (empieza por 0x04).
4AES-256-GCM con IV de 12 bytes al azar y la epk como AAD. Sin el AAD cifra igual, y el destinatario no puede abrirlo.
5ct = texto cifrado con el tag de 16 bytes pegado al final, no en un campo aparte.
6El sobre es base64 de {"v":2,"ct":…,"iv":…,"epk":…}, con los tres valores en base64.

Lo que más falla al implementarlo

  • Poner el tag de GCM en un campo aparte. Va dentro de ct, al final.
  • Usar los bytes «mínimos» del secreto ECDH en vez de 32 con ceros por delante. Cuando el secreto empieza por un byte cero, la clave sale distinta: falla una vez cada 256, o sea que funciona en tus pruebas y falla en producción.
  • Olvidar el AAD.
  • Usar la clave pública comprimida (33 bytes). Tienen que ser 65 y empezar por 0x04.

Implementación de referencia

En PHP plano, solo con OpenSSL. Está comprobada contra la propia aplicación: una prueba automática coge un sobre hecho con este código y lo abre con el mismo descifrador que usa el móvil.

function llEciesV2Cifrar($strTexto, $strClavePubB64) { $strPub = base64_decode(trim($strClavePubB64), true); // 65 bytes, 0x04... $objEfimera = openssl_pkey_new(['private_key_type' => OPENSSL_KEYTYPE_EC, 'curve_name' => 'prime256v1']); $arrDet = openssl_pkey_get_details($objEfimera); $strEpk = "\x04" . str_pad($arrDet['ec']['x'], 32, "\0", STR_PAD_LEFT) . str_pad($arrDet['ec']['y'], 32, "\0", STR_PAD_LEFT); $strZ = openssl_pkey_derive($objDestinatario, $objEfimera, 32); $strZ = str_pad($strZ, 32, "\0", STR_PAD_LEFT); // SIEMPRE 32 $strClave = hash_hkdf('sha256', $strZ, 32, 'LOOKLOCK-v2', $strEpk); $strIv = random_bytes(12); $strTag = ''; $strCt = openssl_encrypt($strTexto, 'aes-256-gcm', $strClave, OPENSSL_RAW_DATA, $strIv, $strTag, $strEpk, 16); // epk = AAD return base64_encode(json_encode([ 'v' => 2, 'ct' => base64_encode($strCt . $strTag), // tag PEGADO 'iv' => base64_encode($strIv), 'epk' => base64_encode($strEpk), ])); }

La versión completa, con el descifrado para tus propias pruebas y el detalle de cómo se compone la clave pública para OpenSSL, se envía con las credenciales al activar el acceso.

Cupo

Cada respuesta correcta lleva dos cabeceras con lo que te queda, para que no tengas que preguntarlo:

X-Cupo-Tipo: mensual X-Cupo-Restante: 9985

Una petición rechazada no gasta cupo. Al agotarlo, la respuesta es 429 y sigue funcionando /cuenta, para que puedas comprobar el estado.

Errores

Todos traen un strCodigo estable —eso es lo que debe mirar tu programa— y un strError en texto, que puede cambiar de redacción. No compares el texto.

HTTPstrCodigoQué pasa
401credencial_invalidaFalta la cabecera o el secreto no es el que corresponde.
401clave_revocadaEsa clave ya no está activa.
403empresa_no_verificadaPendiente de verificar, rechazada o suspendida.
403ambito_insuficienteTu plan no incluye eso. Los planes gratuitos no envían.
404usuario_no_encontradoEse código no existe o todavía no puede recibir mensajes.
400sobre_invalidoLo que enviaste no tiene forma de sobre ECIES v2.
413sobre_demasiado_grandeMás de 256 KB. Para ficheros, manda un mensaje con un enlace.
429cupo_mensual_agotadoSe acabó el cupo del mes.
429cupo_de_prueba_agotadoSe acabaron las consultas de prueba.

Qué apuntamos de tus llamadas

Qué clave llamó, a qué endpoint, con qué código de respuesta y cuánto tardó. Nada más. Ni destinatarios, ni contenidos, ni el sobre.

Y no por pereza: un registro con destinatarios sería el mapa de con quién habla cada cliente tuyo. Eso es exactamente lo que LOOKLOCK CHAT promete no tener, y tenerlo lo haría falso por mucho que el cifrado fuera perfecto. El registro se purga a los 90 días.

Solicitar acceso Comparison