Documentação da API
Uma API REST para criar, ver e gerir segredos. Todos os pedidos e respostas utilizam JSON, e toda a encriptação e desencriptação acontece do seu lado, pelo que o texto em claro nunca chega aos nossos servidores.
Visão geral
O URL base para todos os endpoints da API é:
https://password.link/api
Pode utilizar a API para tratar a encriptação e a desencriptação do segredo fora do nosso serviço, sem precisar de carregar quaisquer activos nossos. Também lhe permite utilizar qualquer tipo de método de entrega para a parte da palavra-passe pública (metade da palavra-passe que é utilizada para derivar a chave de encriptação do segredo) e, basicamente, criar qualquer tipo de configuração personalizada para visualizar o segredo.
Para código completo e funcional, consulte os Exemplos de API.
Autenticação
Cada pedido deve ser autenticado com uma chave de API, enviada no cabeçalho Authorization:
Authorization: ApiKey public_key_abcd...
Existem dois tipos de chaves de API:
| Tipo de chave | Descrição |
|---|---|
| Chave de API pública | Destinada à criação de uma página personalizada e autoalojada para ver segredos. Pode ser utilizada em scripts públicos. Apenas permite ver e confirmar segredos. |
| Chave de API privada | Necessária para todas as outras ações da API. Deve ser sempre mantida privada. |
Ambas as chaves API contêm o tipo da chave na própria chave para que possam ser facilmente distinguidas.
Cada endpoint abaixo mostra o tipo de chave que requer.
Erros
Quando um pedido falha, a resposta contém um objeto de erro:
{
"data": null,
"metadata": null,
"error": {
"message": "Ciphertext can't be blank",
"field": "ciphertext"
}
}
| Campo | Descrição |
|---|---|
message |
A mensagem de erro completa. |
field |
O campo a que o erro se refere, quando se trata de um erro de validação. |
O código de estado HTTP da resposta também indica o tipo de erro:
| Código de estado | Descrição |
|---|---|
403 Forbidden |
O pedido não foi permitido, por exemplo devido a uma chave de API inválida. |
404 Not Found |
O recurso solicitado não foi encontrado. |
422 Unprocessable Content |
O pedido foi compreendido mas falhou a validação, por exemplo devido a um parâmetro em falta ou inválido. |
Encriptação de segredos
Os segredos são encriptados no lado do cliente antes de serem enviados para a API. Esta secção descreve os formatos de palavra-passe e de texto cifrado que o serviço espera.
As partes da palavra-passe
A palavra-passe que é utilizada para encriptar o segredo no AES deve consistir em duas cadeias de 18 caracteres. A chave de encriptação real será a concatenação destas duas cadeias ("parte privada" + "parte pública") e é derivada da palavra-passe utilizando o PBKDF2.
Password: fkgjbnvlakwiejgutnFIGKEOTIRUBNAKQJRL
=> Private part: fkgjbnvlakwiejgutn
=> Public part: FIGKEOTIRUBNAKQJRL
A parte privada é enviada para a API (codificada em Base64) e armazenada com o segredo. A parte pública nunca é enviada para a API e normalmente é entregue no próprio link, pelo que nós nunca podemos desencriptar o segredo.
Se utilizar a página de visualização do segredo fornecida por nós, também deve codificar a parte pública em Base64. Se utilizar uma página de visualização autoalojada, pode usar o mesmo método ou criar o seu próprio. Consulte os Exemplos de API para implementações de referência.
Formato do texto cifrado
O texto cifrado é um objeto JSON, codificado em Base64:
{
"cipher": "<Base64 encoded AES-GCM ciphertext>",
"iv": "<Base64 encoded 12-byte initialization vector>",
"salt": "<Base64 encoded 16-byte PBKDF2 salt>",
"iter": 10000
}
Deve utilizar as seguintes definições para o AES ao encriptar o segredo:
| Definição | Valor |
|---|---|
| Modo | AES-GCM com uma etiqueta de autenticação de 128 bits anexada ao texto cifrado (predefinição do Web Crypto) |
| Tamanho da chave | 256 bits |
| Derivação da chave | PBKDF2 com SHA-256 |
| Iterações PBKDF2 | O valor do campo iter. Intervalo permitido 1000-1000000, recomendamos 10000. |
| Vetor de inicialização | 12 bytes aleatórios |
| Salt | 16 bytes aleatórios |
Formato SJCL legado (obsoleto)
Os textos cifrados criados com a Stanford Javascript Crypto Library (SJCL) continuam a ser aceites: uma cadeia JSON de texto cifrado compatível com SJCL codificada em Base64, utilizando AES-GCM ("mode:gcm"), uma chave de 256 bits ("ks:256") e 10000 iterações PBKDF2 ("iter:10000"). Este formato está obsoleto e o seu suporte será removido no futuro.
Desencriptação de segredos
A API Ver segredo devolve o texto cifrado exatamente como foi armazenado. Os segredos criados na aplicação web utilizam o formato Web Crypto descrito acima. Os segredos criados por clientes da API mais antigos, pela extensão do Chrome ou por ligações ainda não abertas podem utilizar o formato SJCL legado.
Uma página de visualização autoalojada tem de suportar ambos os formatos. Depois de descodificar o texto cifrado de Base64 para JSON, verifique se existe uma chave ct: se estiver presente, desencripte com SJCL; caso contrário, desencripte com Web Crypto. Consulte o exemplo Ver segredo.
Os clientes da API que apenas criam segredos não precisam de alterações: os textos cifrados SJCL continuam a ser aceites na criação. Os clientes que desencriptam segredos obtidos da API têm de adicionar suporte para Web Crypto, caso contrário falharão nos segredos criados na aplicação web.
Criar segredo
Cria um segredo encriptado e devolve o seu ID. O texto cifrado deve ser criado conforme descrito em Encriptação de segredos. Devolve 201 Created em caso de sucesso.
Parâmetros do pedido
| Parâmetro | Tipo | Descrição |
|---|---|---|
ciphertextobrigatório |
string |
Uma cadeia JSON de texto cifrado do segredo compatível com Web Crypto, codificada em Base64. Também são aceites textos cifrados antigos compatíveis com SJCL (obsoleto). |
password_part_privateobrigatório |
string |
A parte privada da palavra-passe que foi utilizada para encriptar o segredo, codificada em Base64. |
password_part_public |
string |
A parte pública da palavra-passe, codificada em Base64. Necessária apenas quando se utiliza email_to para que a API possa enviar por email o link alojado do segredo. |
description |
string |
Uma descrição para o segredo. Não pode ser vista ao visualizar o segredo. |
message |
string |
Uma mensagem para o segredo. Será mostrada juntamente com o segredo. |
expiration |
integer |
Um tempo de expiração para o segredo, em horas. Valores possíveis: 1-500. |
view_button |
boolean |
Mostrar um botão para ver o segredo em vez de mostrar o segredo imediatamente após abrir o link. |
captcha |
boolean |
Mostrar um CAPTCHA simples antes de mostrar o segredo, principalmente para bloquear scanners automatizados. |
password |
string |
Uma palavra-passe para o segredo. |
max_views |
integer |
Quantas vezes o segredo pode ser visto. Valores possíveis: 1-100. |
email_to |
string |
Destinatários de email separados por vírgulas que devem receber o link do segredo criado. Requer password_part_public. |
otp_email_recipient |
string |
Endereço de e-mail que recebe uma palavra-passe de utilização única. Quando definido, o destinatário deve introduzir o código enviado por e-mail antes de poder ver o Secret. |
otp_recipient |
string |
Aceite como alias de otp_email_recipient. Prefira otp_email_recipient para novas integrações. |
otp_sms_recipient |
string |
Número de telefone que recebe uma palavra-passe de utilização única por SMS, em formato internacional começando com + e sem espaços. |
allowed_ips |
string |
Endereços IP ou intervalos CIDR separados por vírgulas autorizados a ver o Secret. |
allowed_locations |
array |
Array de códigos de país ISO 3166-1 alfa-2 autorizados a ver o Secret. |
available_after |
datetime |
Data e hora antes das quais o Secret não pode ser visualizado. |
secret_folder_id |
string |
ID de uma pasta de Secrets existente pertencente ao utilizador da chave API. |
reply_enabled |
boolean |
Ativar uma resposta de utilização única do destinatário depois de o Secret ter sido visualizado. |
ack_required |
boolean |
Exigir confirmação do destinatário antes de o Secret poder ser visualizado. |
ack_mode |
string |
Modo de confirmação. Use checkbox ou phrase. |
ack_phrase |
string |
Frase que o destinatário deve escrever. Obrigatória quando ack_required é true e ack_mode é phrase. |
ack_disclosure_text |
string |
Texto de divulgação mostrado ao destinatário, até 500 caracteres. |
ack_collect_name |
boolean |
recolher o nome do destinatário com a confirmação. |
ack_name_required |
boolean |
Exigir o nome do destinatário. Isto também ativa ack_collect_name. |
ack_collect_org |
boolean |
recolher a organização do destinatário com a confirmação. |
attachment |
object |
Metadados para um anexo de ficheiro encriptado, consulte Anexos. Requer um plano ativo. |
attachment.file_name |
string |
O nome original do arquivo mostrado ao destinatário. Obrigatório quando é fornecido um anexo. |
attachment.file_type |
string |
O tipo MIME original, por exemplo text/plain ou application/pdf. Obrigatório quando é fornecido um anexo. |
attachment.file_size |
integer |
O tamanho original não criptografado do arquivo em bytes. Obrigatório quando é fornecido um anexo. |
As Definições de Secrets da Equipa podem desativar, exigir ou impor predefinições para opções de Secret suportadas. A API aplica essas regras da equipa ao criar um Secret.
Exemplo de pedido
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
}'
Exemplo de resposta
{
"data": {
"id": "dT5g"
},
"metadata": {
"secrets_total": 70,
"secrets_usage": 25,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
O link para o segredo é formado combinando o URL da página de visualização alojada, o ID do segredo e a parte pública da palavra-passe codificada em Base64:
https://password.link/<id>/#<public password part, Base64>
Anexos
O carregamento de um anexo é um processo de dois passos: primeiro crie o segredo com os metadados do anexo (consulte Criar segredo), depois encripte e carregue o payload encriptado do anexo para o URL de carregamento devolvido.
O conteúdo do segredo e o conteúdo do anexo são criptografados separadamente. Ambos utilizam dados AES-GCM compatíveis com Web Crypto, codificados em Base64, mas os campos do payload são codificados de forma diferente: o payload do segredo contém campos codificados em Base64 e um campo iter, enquanto o payload do anexo contém campos de cadeias binárias em bruto.
Encriptação do anexo
Antes da criptografia, represente o arquivo como uma URL de dados:
data:<mime-type>;base64,<base64 file bytes>
A palavra-passe de encriptação do anexo é a parte privada em bruto da palavra-passe concatenada com a parte pública em bruto (sem codificação Base64).
Encripte essa cadeia data URL com AES-GCM usando PBKDF2-SHA256, 10000 iterações, uma chave derivada de 256 bits, um salt aleatório de 16 bytes e um IV aleatório de 12 bytes. Guarde o payload encriptado do anexo como um objeto JSON e depois codifique a cadeia JSON em Base64:
{
"cipher": "<binary string>",
"iv": "<binary string>",
"salt": "<binary string>"
}
Carregamento do ficheiro encriptado
Quando é incluído um anexo, a resposta de criação do segredo contém um destino de carregamento em data.attachment.upload:
{
"data": {
"id": "dT5g",
"attachment": {
"file_name": "example.txt",
"upload": {
"url": "/api/secrets/dT5g/attachment",
"fields": {},
"metadata": {}
}
}
},
"metadata": {}
}
Carregue o JSON encriptado codificado em Base64 como text/plain usando multipart/form-data para o upload.url devolvido. Adicione todos os pares chave/valor devolvidos em upload.metadata ou upload.fields aos dados do formulário antes de adicionar o ficheiro encriptado. O campo do ficheiro encriptado deve chamar-se file.
Para URLs de upload da Password.link, inclua a mesma chave de API privada no cabeçalho Authorization: ApiKey <key>. URLs de upload direto para armazenamento, como URLs S3 pré-assinadas, devem receber apenas os campos de formulário retornados e o campo file criptografado.
URLs de upload hospedadas no Password.link incluem um objeto fields vazio. URLs de upload direto para armazenamento, como URLs S3 pré-assinadas, retornam os campos de assinatura em metadata.
Os limites de tamanho dos anexos dependem da quota da conta ou da equipa, e o carregamento encriptado é maior do que o ficheiro original porque o ficheiro é convertido em Base64 e encriptado.
Ver segredo
Obtém o texto cifrado, a parte privada da palavra-passe e outros detalhes de um segredo. Este endpoint pode ser utilizado para criar uma página personalizada e autoalojada para ver o segredo que não carrega scripts nem outros recursos do nosso serviço. Devolve 200 OK em caso de sucesso.
A obtenção bem sucedida de um segredo marca-o automaticamente como visualizado e, assim, elimina o texto cifrado e a parte da palavra-passe privada da nossa base de dados, tornando impossível visualizar novamente o segredo.
O texto cifrado pode estar no formato Web Crypto ou no formato SJCL legado. Detete os payloads SJCL pela presença de uma chave ct no JSON descodificado. Consulte Desencriptação de segredos.
Exemplo de pedido
curl -H "Authorization: ApiKey public_key_abcd" \
https://password.link/api/secrets/dT5g
Exemplo de resposta
{
"data": {
"id": "dT5g",
"ciphertext": "eyJjaXBoZXIiOiJRc3hxsN3...aXRlciI6MTAwMDB9",
"password_part_private": "ZmtnamJudmxha3dpZWpndXRu",
"message": "Here are the credentials we talked about"
},
"metadata": null
}
Confirmar Secret
Envia a confirmação do destinatário para um segredo criado com ack_required e devolve os mesmos dados do segredo que View Secret quando a confirmação é válida. Devolve 200 OK em caso de sucesso.
Se for necessária confirmação, GET /api/secrets/<id> devolve 403 Forbidden com secret_status definido como ack_required até que este endpoint seja utilizado.
Os payloads de confirmação inválidos ou incompletos também devolvem 403 Forbidden. Não são devolvidos como erros de validação.
Parâmetros do pedido
| Parâmetro | Tipo | Descrição |
|---|---|---|
ack_confirmed |
boolean |
Definir como true para a confirmação por caixa de seleção. |
ack_phrase |
string |
Necessário para confirmação por frase, e deve corresponder à frase configurada para o Secret. |
ack_signer_name |
string |
Nome do destinatário, necessário quando a recolha de nome está ativada e marcada como obrigatória. |
ack_signer_org |
string |
Organização do destinatário, guardada quando a recolha de organização está ativada. |
Exemplo de pedido
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"}'
Segredos da lista
Obtém uma lista de segredos. Não contém os textos cifrados nem as partes privadas das palavras-passe, apenas IDs, descrições e semelhantes. Devolve 200 OK em caso de sucesso.
A quantidade máxima de resultados devolvidos por cada consulta está limitada a 50. Pode controlar o offset com o parâmetro de consulta opcional offset, por exemplo: /api/secrets?offset=50
Exemplo de pedido
curl -H "Authorization: ApiKey private_key_abcd" \
https://password.link/api/secrets
Exemplo de resposta
{
"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
}
}
Atualizar Secret
Atualiza as definições e os metadados suportados de um segredo existente. Devolve 204 No Content em caso de sucesso.
PATCH não substitui o conteúdo encriptado do segredo, não reenvia emails de entrega nem cria metadados de carregamento de anexos. Use Create Secret para o texto cifrado, as partes da palavra-passe, a entrega do link e os anexos.
Os seguintes parâmetros podem ser atualizados, com o mesmo significado que em 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 e os metadados de anexos só podem ser definidos na criação. São ignorados pelo PATCH.
Exemplo de pedido
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"}'
Eliminar segredo
Elimina um segredo. Devolve 200 OK em caso de sucesso.
Exemplo de pedido
curl -H "Authorization: ApiKey private_key_abcd" \
-X DELETE https://password.link/api/secrets/dT5g
Exemplo de resposta
{
"data": null,
"metadata": {
"secrets_total": 69,
"secrets_usage": 24,
"secrets_allowance": 100,
"secret_requests_total": 10,
"secret_requests_allowance": 100
}
}
Criar pasta de Secrets
Cria uma pasta de segredos. Devolve 201 Created em caso de sucesso.
Parâmetros do pedido
| Parâmetro | Tipo | Descrição |
|---|---|---|
nameobrigatório |
string |
Nome da pasta. |
description |
string |
Descrição da pasta. |
Exemplo de resposta
{
"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 pastas de Secrets
Obtém uma lista de pastas de segredos. Devolve 200 OK em caso de sucesso.
Exemplo de resposta
{
"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
}
}
Atualizar pasta de Secrets
Atualiza o nome e a descrição de uma pasta de segredos. Aceita os mesmos parâmetros que Create Secret Folder e devolve 204 No Content em caso de sucesso.
Eliminar a pasta secreta
Elimina uma pasta de segredos. Devolve 200 OK em caso de sucesso.
Criar pedido secreto
Cria um novo pedido de segredo. Devolve 201 Created em caso de sucesso.
Parâmetros do pedido
| Parâmetro | Tipo | Descrição |
|---|---|---|
description |
string |
Descrição do pedido secreto. |
message |
string |
Mensagem para o visualizador do Pedido Secreto. |
expiration |
integer |
Tempo de expiração do Pedido Secreto, em horas. |
limit |
integer |
Limite de utilização do pedido secreto. |
send_request_to_email |
string |
Envia a ligação do Pedido Secreto criada para o endereço de correio eletrónico indicado. |
send_request_to_sms |
string |
Enviar a ligação do Secret Request criado para o número de telefone indicado. |
send_to_email |
string |
Envia a ligação secreta criada utilizando o Pedido de Segredo para o endereço de correio eletrónico indicado. |
secret_description |
string |
Descrição para o Segredo criado utilizando o Pedido de Segredo. |
secret_message |
string |
Mensagem para o Segredo criado utilizando o Pedido de Segredo. |
secret_expiration |
integer |
Tempo de expiração para o Segredo criado utilizando o Pedido de Segredo, em horas. |
secret_password |
string |
Palavra-passe para o Secret criado usando o Secret Request. |
secret_max_views |
integer |
Limite de visualização para o Segredo criado utilizando o Pedido de Segredo. |
template_id |
string |
ID do modelo de pedido a usar. |
secret_allowed_emails |
string |
Endereços de e-mail ou domínios separados por vírgulas autorizados a abrir Secrets criados com este Secret Request. |
secret_allowed_ips |
string |
Endereços IP ou intervalos CIDR separados por vírgulas autorizados a abrir Secrets criados com este Secret Request. |
Exemplo de pedido
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}'
Exemplo de resposta
{
"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 Pedidos secretos
Obtém uma lista de pedidos de segredo. Devolve 200 OK em caso de sucesso.
A quantidade máxima de resultados devolvidos por cada consulta está limitada a 50. Pode controlar o offset com o parâmetro de consulta opcional offset, por exemplo: /api/secret_requests?offset=50
A resposta da lista não inclui secret_allowed_emails nem secret_allowed_ips.
Exemplo de pedido
curl -H "Authorization: ApiKey private_key_abcd" \
https://password.link/api/secret_requests
Exemplo de resposta
{
"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
}
}
Pedido de eliminação de segredo
Elimina um pedido de segredo. Devolve 200 OK em caso de sucesso.
Exemplo de pedido
curl -H "Authorization: ApiKey private_key_abcd" \
-X DELETE https://password.link/api/secret_requests/5e976e6e-d205-4f58-8df9-5ac0048bc702