Documentación API
Una API REST para crear, ver y gestionar secretos. Todas las solicitudes y respuestas utilizan JSON, y todo el cifrado y descifrado se realiza en su lado, por lo que el texto sin cifrar nunca llega a nuestros servidores.
Visión general
La URL base para todos los puntos de conexión de la API es:
https://password.link/api
Puedes utilizar la API para manejar tanto el cifrado como el descifrado del secreto fuera de nuestro servicio, sin necesidad de cargar ningún activo nuestro. También le permite utilizar cualquier tipo de método de entrega para la parte de la contraseña pública (la mitad de la contraseña que se utiliza para derivar la clave de cifrado para el secreto de) y, básicamente, crear cualquier tipo de configuración personalizada para ver el secreto.
Para ver código completo y funcional, consulte los Ejemplos de API.
Autenticación
Cada solicitud debe autenticarse con una clave API, enviada en la cabecera Authorization:
Authorization: ApiKey public_key_abcd...
Existen dos tipos de claves API:
| Tipo de clave | Descripción |
|---|---|
| Clave API pública | Pensada para crear una página personalizada y autoalojada para ver secretos. Puede usarse en scripts públicos. Solo permite ver y confirmar secretos. |
| Clave API privada | Necesaria para todas las demás acciones de la API. Debe mantenerse siempre en privado. |
Ambas claves API contienen el tipo de clave en la propia clave para que puedan distinguirse fácilmente.
Cada punto de conexión a continuación muestra qué tipo de clave requiere.
Errores
Cuando una solicitud falla, la respuesta contiene un objeto de error:
{
"data": null,
"metadata": null,
"error": {
"message": "Ciphertext can't be blank",
"field": "ciphertext"
}
}
| Campo | Descripción |
|---|---|
message |
El mensaje de error completo. |
field |
El campo al que se refiere el error, cuando se trata de un error de validación. |
El código de estado HTTP de la respuesta también indica el tipo de error:
| Código de estado | Descripción |
|---|---|
403 Forbidden |
La solicitud no fue permitida, por ejemplo debido a una clave API no válida. |
404 Not Found |
No se encontró el recurso solicitado. |
422 Unprocessable Content |
La solicitud se entendió pero no superó la validación, por ejemplo debido a un parámetro que falta o no es válido. |
Cifrado de secretos
Los secretos se cifran en el lado del cliente antes de enviarse a la API. Esta sección describe los formatos de contraseña y de texto cifrado que espera el servicio.
Las partes de la contraseña
La contraseña que se utiliza para cifrar el secreto en AES debe constar de dos cadenas de 18 caracteres. La clave de cifrado real será la concatenación de estas dos cadenas ("parte privada" + "parte pública") y se obtiene a partir de la contraseña utilizando PBKDF2.
Password: fkgjbnvlakwiejgutnFIGKEOTIRUBNAKQJRL
=> Private part: fkgjbnvlakwiejgutn
=> Public part: FIGKEOTIRUBNAKQJRL
La parte privada se envía a la API (codificada en Base64) y se almacena con el secreto. La parte pública nunca se envía a la API y normalmente se entrega en el propio enlace, por lo que nosotros nunca podemos descifrar el secreto.
Si utiliza la página para ver el secreto proporcionada por nosotros, también debe codificar la parte pública en Base64. Si utiliza una página autoalojada para ver el secreto, puede usar el mismo método o crear el suyo propio. Consulte los Ejemplos de API para ver implementaciones de referencia.
Formato del texto cifrado
El texto cifrado es un objeto JSON, codificado en Base64:
{
"cipher": "<Base64 encoded AES-GCM ciphertext>",
"iv": "<Base64 encoded 12-byte initialization vector>",
"salt": "<Base64 encoded 16-byte PBKDF2 salt>",
"iter": 10000
}
Debe utilizar la siguiente configuración para AES al cifrar el secreto:
| Ajuste | Valor |
|---|---|
| Modo | AES-GCM con una etiqueta de autenticación de 128 bits añadida al final del texto cifrado (valor predeterminado de Web Crypto) |
| Tamaño de la clave | 256 bits |
| Derivación de la clave | PBKDF2 con SHA-256 |
| Iteraciones PBKDF2 | El valor del campo iter. Rango permitido 1000-1000000, recomendamos 10000. |
| Vector de inicialización | 12 bytes aleatorios |
| Sal | 16 bytes aleatorios |
Formato SJCL heredado (obsoleto)
Los textos cifrados creados con la Stanford Javascript Crypto Library (SJCL) siguen aceptándose: una cadena JSON de texto cifrado compatible con SJCL codificada en Base64, que utiliza AES-GCM ("mode:gcm"), una clave de 256 bits ("ks:256") y 10000 iteraciones PBKDF2 ("iter:10000"). Este formato está obsoleto y su compatibilidad se eliminará en el futuro.
Descifrado de secretos
La API Ver Secreto devuelve el texto cifrado exactamente como se almacenó. Los secretos creados en la aplicación web utilizan el formato Web Crypto descrito arriba. Los secretos creados por clientes de la API antiguos, por la extensión de Chrome o por enlaces aún sin abrir pueden utilizar el formato SJCL heredado.
Una página de visualización autoalojada debe gestionar ambos formatos. Tras descodificar el texto cifrado de Base64 a JSON, compruebe si existe una clave ct: si está presente, descifre con SJCL; en caso contrario, descifre con Web Crypto. Consulte el ejemplo de Ver Secreto.
Los clientes de la API que solo crean secretos no necesitan cambios: los textos cifrados con SJCL siguen aceptándose al crear. Los clientes que descifran secretos obtenidos de la API deben añadir compatibilidad con Web Crypto o fallarán con los secretos creados en la aplicación web.
Crear secreto
Crea un secreto cifrado y devuelve su ID. El texto cifrado debe crearse como se describe en Cifrado de secretos. Devuelve 201 Created si tiene éxito.
Parámetros de la solicitud
| Parámetro | Tipo | Descripción |
|---|---|---|
ciphertextobligatorio |
string |
Una cadena JSON de texto cifrado del secreto compatible con Web Crypto, codificada en Base64. También se aceptan textos cifrados heredados compatibles con SJCL (obsoleto). |
password_part_privateobligatorio |
string |
La parte privada de la contraseña que se utilizó para cifrar el secreto, codificada en Base64. |
password_part_public |
string |
La parte pública de la contraseña, codificada en Base64. Solo es necesaria cuando se usa email_to para que la API pueda enviar por correo electrónico el enlace alojado del secreto. |
description |
string |
Una descripción para el secreto. No se puede ver al visualizar el secreto. |
message |
string |
Un mensaje para el secreto. Se mostrará junto con el secreto. |
expiration |
integer |
Un tiempo de expiración para el secreto, en horas. Valores posibles: 1-500. |
view_button |
boolean |
Mostrar un botón para ver el secreto en lugar de mostrar el secreto inmediatamente después de abrir el enlace. |
captcha |
boolean |
Mostrar un CAPTCHA simple antes de mostrar el secreto, principalmente para bloquear escáneres automatizados. |
password |
string |
Una contraseña para el secreto. |
max_views |
integer |
Cuántas veces se puede ver el secreto. Valores posibles: 1-100. |
email_to |
string |
Destinatarios de correo electrónico separados por comas que deben recibir el enlace del secreto creado. Requiere password_part_public. |
otp_email_recipient |
string |
Dirección de correo que recibe una contraseña de un solo uso. Cuando se establece, el destinatario debe introducir el código enviado por correo antes de poder ver el Secret. |
otp_recipient |
string |
Se acepta como alias de otp_email_recipient. Prefiera otp_email_recipient para nuevas integraciones. |
otp_sms_recipient |
string |
Número de teléfono que recibe una contraseña de un solo uso por SMS, en formato internacional comenzando con + y sin espacios. |
allowed_ips |
string |
Direcciones IP o rangos CIDR separados por comas con permiso para ver el Secret. |
allowed_locations |
array |
Array de códigos de país ISO 3166-1 alfa-2 con permiso para ver el Secret. |
available_after |
datetime |
Fecha y hora antes de las cuales no se puede ver el Secret. |
secret_folder_id |
string |
ID de una carpeta de Secrets existente propiedad del usuario de la clave API. |
reply_enabled |
boolean |
Habilitar una respuesta de un solo uso del destinatario después de que se haya visto el Secret. |
ack_required |
boolean |
Requerir confirmación del destinatario antes de que se pueda ver el Secret. |
ack_mode |
string |
Modo de confirmación. Use checkbox o phrase. |
ack_phrase |
string |
Frase que el destinatario debe escribir. Obligatoria cuando ack_required es true y ack_mode es phrase. |
ack_disclosure_text |
string |
Texto de divulgación mostrado al destinatario, hasta 500 caracteres. |
ack_collect_name |
boolean |
recopilar el nombre del destinatario con la confirmación. |
ack_name_required |
boolean |
Requerir el nombre del destinatario. Esto también activa ack_collect_name. |
ack_collect_org |
boolean |
recopilar la organización del destinatario con la confirmación. |
attachment |
object |
Metadatos para un archivo adjunto cifrado, consulte Archivos adjuntos. Requiere un plan activo. |
attachment.file_name |
string |
El nombre de archivo original que se muestra al destinatario. Obligatorio cuando se proporciona un archivo adjunto. |
attachment.file_type |
string |
El tipo MIME original, por ejemplo text/plain o application/pdf. Obligatorio cuando se proporciona un archivo adjunto. |
attachment.file_size |
integer |
El tamaño original sin cifrar del archivo en bytes. Obligatorio cuando se proporciona un archivo adjunto. |
La Configuración de Secrets del equipo puede deshabilitar, requerir o imponer valores predeterminados para las opciones de Secret compatibles. La API aplica esas reglas del equipo al crear un Secret.
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
-H "Content-Type: application/json" \
-X POST https://password.link/api/secrets \
-d '{
"ciphertext": "eyJjaXBoZXIiOiJRc3hxsN3...aXRlciI6MTAwMDB9",
"password_part_private": "ZmtnamJudmxha3dpZWpndXRu",
"description": "Database credentials",
"expiration": 24,
"view_button": true,
"max_views": 1
}'
Ejemplo de respuesta
{
"data": {
"id": "dT5g"
},
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
El enlace al secreto se forma combinando la URL de la página de visualización alojada, el ID del secreto y la parte pública de la contraseña codificada en Base64:
https://password.link/<id>/#<public password part, Base64>
Archivos adjuntos
Subir un archivo adjunto es un proceso de dos pasos: primero cree el secreto con los metadatos del adjunto (consulte Crear secreto) y luego cifre y suba la carga cifrada del adjunto a la URL de subida devuelta.
El contenido del secreto y el contenido del adjunto se cifran por separado. Ambos utilizan datos AES-GCM compatibles con Web Crypto, codificados en Base64, pero los campos de la carga útil se codifican de forma diferente: la carga útil del secreto contiene campos codificados en Base64 y un campo iter, mientras que la carga útil del adjunto contiene campos de cadenas binarias sin procesar.
Cifrado del archivo adjunto
Antes de cifrar, represente el archivo como una URL de datos:
data:<mime-type>;base64,<base64 file bytes>
La contraseña de cifrado del adjunto es la parte privada sin procesar de la contraseña concatenada con la parte pública sin procesar (sin codificación Base64).
Cifre esa cadena data URL con AES-GCM usando PBKDF2-SHA256, 10000 iteraciones, una clave derivada de 256 bits, una sal aleatoria de 16 bytes y un IV aleatorio de 12 bytes. Guarde la carga cifrada del adjunto como un objeto JSON y luego codifique la cadena JSON en Base64:
{
"cipher": "<binary string>",
"iv": "<binary string>",
"salt": "<binary string>"
}
Subida del archivo cifrado
Cuando se incluye un archivo adjunto, la respuesta de creación del secreto contiene un destino de subida en data.attachment.upload:
{
"data": {
"id": "dT5g",
"attachment": {
"file_name": "example.txt",
"upload": {
"url": "/api/secrets/dT5g/attachment",
"fields": {},
"metadata": {}
}
}
},
"metadata": {}
}
Suba el JSON cifrado codificado en Base64 como text/plain usando multipart/form-data a la upload.url devuelta. Añada todos los pares clave/valor devueltos en upload.metadata o upload.fields a los datos del formulario antes de añadir el archivo cifrado. El campo del archivo cifrado debe llamarse file.
Para las URL de carga de Password.link, incluya la misma clave API privada en el encabezado Authorization: ApiKey <key>. Las URL de carga directa al almacenamiento, como las URL S3 prefirmadas, solo deben recibir los campos de formulario devueltos y el campo file cifrado.
Las URL de carga alojadas en Password.link incluyen un objeto fields vacío. Las URL de carga directa a almacenamiento, como las URL prefirmadas de S3, devuelven los campos de firma en metadata.
Los límites de tamaño de los adjuntos dependen de la asignación de la cuenta o del equipo, y la subida cifrada es más grande que el archivo original porque el archivo se convierte a Base64 y se cifra.
Ver Secreto
Obtiene el texto cifrado, la parte privada de la contraseña y otros detalles de un secreto. Este punto de conexión puede usarse para crear una página personalizada y autoalojada para ver el secreto que no cargue scripts ni otros recursos de nuestro servicio. Devuelve 200 OK si tiene éxito.
Cuando se obtiene un secreto con éxito, se marca automáticamente como visto y, por lo tanto, se borra el texto cifrado y la contraseña privada de nuestra base de datos, lo que hace imposible volver a ver el secreto.
El texto cifrado puede tener el formato Web Crypto o el formato SJCL heredado. Detecte las cargas SJCL por la presencia de una clave ct en el JSON descodificado. Consulte Descifrado de secretos.
Ejemplo de solicitud
curl -H "Authorization: ApiKey public_key_abcd" \
https://password.link/api/secrets/dT5g
Ejemplo de respuesta
{
"data": {
"id": "dT5g",
"ciphertext": "eyJjaXBoZXIiOiJRc3hxsN3...aXRlciI6MTAwMDB9",
"password_part_private": "ZmtnamJudmxha3dpZWpndXRu",
"message": "Here are the credentials we talked about"
},
"metadata": null
}
Confirmar Secret
Envía la confirmación del destinatario para un secreto creado con ack_required y devuelve los mismos datos del secreto que View Secret cuando la confirmación es válida. Devuelve 200 OK si tiene éxito.
Si se requiere confirmación, GET /api/secrets/<id> devuelve 403 Forbidden con secret_status establecido en ack_required hasta que se use este punto de conexión.
Las cargas de confirmación no válidas o incompletas también devuelven 403 Forbidden. No se devuelven como errores de validación.
Parámetros de la solicitud
| Parámetro | Tipo | Descripción |
|---|---|---|
ack_confirmed |
boolean |
Establecer en true para la confirmación mediante casilla de verificación. |
ack_phrase |
string |
Requerido para la confirmación con frase, y debe coincidir con la frase configurada para el Secret. |
ack_signer_name |
string |
Nombre del destinatario, requerido cuando la recopilación de nombre está habilitada y marcada como obligatoria. |
ack_signer_org |
string |
Organización del destinatario, almacenada cuando la recopilación de organización está habilitada. |
Ejemplo de solicitud
curl -H "Authorization: ApiKey public_key_abcd" \
-H "Content-Type: application/json" \
-X POST https://password.link/api/secrets/dT5g/acknowledge \
-d '{"ack_confirmed": true, "ack_signer_name": "Jane Doe"}'
Lista Secretos
Obtiene una lista de secretos. No contiene los textos cifrados ni las partes privadas de las contraseñas, solo IDs, descripciones y similares. Devuelve 200 OK si tiene éxito.
La cantidad máxima de resultados devueltos por cada consulta está limitada a 50. Puede controlar el desplazamiento con el parámetro de consulta opcional offset, por ejemplo: /api/secrets?offset=50
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
https://password.link/api/secrets
Ejemplo de respuesta
{
"data": [
{
"id": "dT5g",
"created_at": "2026-07-02T10:00:00.000Z",
"message": "Here are the credentials we talked about",
"description": "Database credentials",
"view_button": true,
"captcha": false,
"password": false,
"expiration": 24,
"expired": false,
"view_times": 1,
"max_views": 1,
"secret_folder_id": "5e976e6e-d205-4f58-8df9-5ac0048bc702",
"views": [
{
"viewed_at": "2026-07-02T12:34:56.000Z",
"viewed_by_ip": "192.0.2.10",
"viewed_by_user_agent": "Mozilla/5.0 ..."
}
]
}
],
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Actualizar Secret
Actualiza los ajustes y metadatos compatibles de un secreto existente. Devuelve 204 No Content si tiene éxito.
PATCH no reemplaza el contenido cifrado del secreto, no reenvía los correos de entrega ni crea metadatos de subida de adjuntos. Use Create Secret para el texto cifrado, las partes de la contraseña, la entrega del enlace y los adjuntos.
Los siguientes parámetros pueden actualizarse, con el mismo significado que en Create Secret:
description, message, expiration, max_views,
view_button, captcha, password,
otp_email_recipient, otp_recipient, otp_sms_recipient,
allowed_ips, allowed_locations, available_after,
secret_folder_id, reply_enabled,
ack_required, ack_mode, ack_phrase, ack_disclosure_text,
ack_collect_name, ack_name_required, ack_collect_org
ciphertext, password_part_private, password_part_public, email_to y los metadatos de adjuntos solo pueden establecerse al crear. PATCH los ignora.
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
-H "Content-Type: application/json" \
-X PATCH https://password.link/api/secrets/dT5g \
-d '{"description": "Updated description", "otp_email_recipient": "recipient@example.com"}'
Borrar secreto
Elimina un secreto. Devuelve 200 OK si tiene éxito.
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
-X DELETE https://password.link/api/secrets/dT5g
Ejemplo de respuesta
{
"data": null,
"metadata": {
"secrets_total": 69,
"secrets_usage": 24,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Crear carpeta de Secrets
Crea una carpeta de secretos. Devuelve 201 Created si tiene éxito.
Parámetros de la solicitud
| Parámetro | Tipo | Descripción |
|---|---|---|
nameobligatorio |
string |
Nombre de la carpeta. |
description |
string |
Descripción de la carpeta. |
Ejemplo de respuesta
{
"data": {
"id": "5e976e6e-d205-4f58-8df9-5ac0048bc702"
},
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Listar carpetas de Secrets
Obtiene una lista de carpetas de secretos. Devuelve 200 OK si tiene éxito.
Ejemplo de respuesta
{
"data": [
{
"id": "5e976e6e-d205-4f58-8df9-5ac0048bc702",
"name": "Clients",
"description": "Client credentials",
"created_at": "2026-07-02T10:00:00.000Z",
"updated_at": "2026-07-02T10:00:00.000Z"
}
],
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Actualizar carpeta de Secrets
Actualiza el nombre y la descripción de una carpeta de secretos. Acepta los mismos parámetros que Create Secret Folder y devuelve 204 No Content si tiene éxito.
Eliminar carpeta secreta
Elimina una carpeta de secretos. Devuelve 200 OK si tiene éxito.
Crear solicitud secreta
Crea una nueva solicitud de secreto. Devuelve 201 Created si tiene éxito.
Parámetros de la solicitud
| Parámetro | Tipo | Descripción |
|---|---|---|
description |
string |
Descripción de la solicitud secreta. |
message |
string |
Para el visor de Peticiones Secretas. |
expiration |
integer |
Tiempo de expiración de la Petición Secreta, en horas. |
limit |
integer |
Límite de uso de la Solicitud Secreta. |
send_request_to_email |
string |
Envía el enlace de solicitud secreta creado a la dirección de correo electrónico indicada. |
send_request_to_sms |
string |
Enviar el enlace de Secret Request creado al número de teléfono indicado. |
send_to_email |
string |
Envía el enlace secreto creado mediante la solicitud de secreto a la dirección de correo electrónico indicada. |
secret_description |
string |
Descripción del secreto creado mediante la solicitud de secreto. |
secret_message |
string |
Para el Secreto creado mediante la Solicitud de Secreto. |
secret_expiration |
integer |
Tiempo de expiración para el Secreto creado usando la Solicitud de Secreto, en horas. |
secret_password |
string |
Contraseña para el Secret creado usando el Secret Request. |
secret_max_views |
integer |
Límite de vistas para el Secreto creado mediante la Solicitud de Secreto. |
template_id |
string |
ID de la plantilla de solicitud que se usará. |
secret_allowed_emails |
string |
Direcciones de correo o dominios separados por comas con permiso para abrir Secrets creados con este Secret Request. |
secret_allowed_ips |
string |
Direcciones IP o rangos CIDR separados por comas con permiso para abrir Secrets creados con este Secret Request. |
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
-H "Content-Type: application/json" \
-X POST https://password.link/api/secret_requests \
-d '{"description": "Request for VPN credentials", "expiration": 48}'
Ejemplo de respuesta
{
"data": {
"id": "5e976e6e-d205-4f58-8df9-5ac0048bc702"
},
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Lista de peticiones secretas
Obtiene una lista de solicitudes de secreto. Devuelve 200 OK si tiene éxito.
La cantidad máxima de resultados devueltos por cada consulta está limitada a 50. Puede controlar el desplazamiento con el parámetro de consulta opcional offset, por ejemplo: /api/secret_requests?offset=50
La respuesta de la lista no incluye secret_allowed_emails ni secret_allowed_ips.
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
https://password.link/api/secret_requests
Ejemplo de respuesta
{
"data": [
{
"id": "5e976e6e-d205-4f58-8df9-5ac0048bc702",
"description": "Request for VPN credentials",
"message": "Please send me the VPN credentials",
"expiration": 48,
"limit": 1,
"send_request_to_email": "request-recipient@example.com",
"send_request_to_sms": "+358401234567",
"send_to_email": "example@example.com",
"secret_description": "VPN credentials",
"secret_message": null,
"secret_expiration": 24,
"secret_max_views": 1,
"secret_password": false,
"template_id": null
}
],
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Borrar solicitud secreta
Elimina una solicitud de secreto. Devuelve 200 OK si tiene éxito.
Ejemplo de solicitud
curl -H "Authorization: ApiKey private_key_abcd" \
-X DELETE https://password.link/api/secret_requests/5e976e6e-d205-4f58-8df9-5ac0048bc702