General
We have a standard REST API for managing secrets. All requests and responses use the JSON format.
You can use the API to handle both encryption and decryption of the secret outside of our service, without needing to load any assets from us. It also allows you to use any kind of delivery method for the public password part (half of the password which is used to derive the encryption key for the secret from) and basically create any kind of custom configuration for viewing the secret.
Code examples
Please see our API examples on how to use the API.
Authentication
We use two kinds of API keys for authentication:
- Public API keys
- Private API keys
Public API keys are meant for creating a custom self-hosted view secret page. All other API actions require a private API key.
Public API keys can be used in public scripts. Private API keys must always be kept private.
Both API keys contain the type of the key in the key itself so they can be easily distinguished.
The API key must be sent in the Authorization: ApiKey <key> header, like:
Authorization: ApiKey public_key_abc...
Errors
In case of unsuccessful query, the response will have an error object.
The object contains the following fields:
- message: the full error message, e.g. "Ciphertext can't be blank"
- field: the field the error is about, e.g. "ciphertext"
The HTTP response status code will also indicate an error, for example:
- 403 Forbidden: the request was not allowed, for example because of invalid API key
- 404 Not Found: the requested secret was not found
View secret
Request type: GET
Request path: https://password.link/api/secrets/<id>
Status code of successful query: 200 OK
Fetch the ciphertext, private password part and other details of a secret. Requires the public API key.
This API query can be used to create a custom self-hosted view secret page which does not load any scripts or other assets from our service.
Successfully fetching a secret automatically marks it as viewed and so deletes the ciphertext and private password part from our database, making it impossible to view the secret again.
Required parameters- id: the id of the secret, for example dT5g
Query example
curl -H "Authorization: ApiKey public_key_abcd" https://password.link/api/secrets/dT5g
Response example
{ "data": { "id": "the ID of the secret", "ciphertext": "the ciphertext of the secret", "password_part_private": "the private password part of the secret", "message": "the message for the secret, if set" }, "metadata": { "secrets_total": 1, "secrets_usage": 1, "secrets_allowance": 1 } }
Code example
Please see our API examples.
Create secret
Request type: POST
Request path: https://password.link/api/secrets
Status code of successful query: 201 Created
This API call also supports adding an attachment to the secret. Please contact us for more details.
Create an encrypted secret.
Encrypting the secret client-side before sending it to our API requires creating an SJCL compatible ciphertext JSON string. Please refer to the SJCL documentation for proper format of the JSON string, and see our API examples for examples on how to create the ciphertext.
Creating the password for encrypting the secret
The password which is used to encrypt the secret in AES must consist of two 18 character long strings. The actual encryption key will be the concatenation of these two strings ("private part" + "public part") and is derived from the password by SJCL using PBKDF2.
Example of creating the private and public password parts:
Password: fkgjbnvlakwiejgutnFIGKEOTIRUBNAKQJRL => Private part: fkgjbnvlakwiejgutn => Public part: FIGKEOTIRUBNAKQJRL
The private part needs to be Base64 encoded before sending over to our API. If you use the view secret page provided by us, you must also Base64 encode the public part. If you use a self-hosted view secret page, you can use the same method or create your own. Please see our API examples for reference implementations.
Required SJCL AES settings
You must use the following settings for AES when encrypting the secret:
- Mode: AES-GCM (SJCL setting: "mode:gcm")
- Key size: 256 bits (SJCL setting: "ks:256")
- Key derivation function: PBKDF2 (SJCL default)
- PBKDF2 iterations: 10000 (SJCL setting: "iter:10000")
Request payload
{ "ciphertext": "ciphertext", "password_part_private": "password_part_private", "description": "description", "message": "message", "expiration": "expiration", "view_button": "view_button", "captcha": "captcha", "password": "password", "max_views": "max_views" }
Request parameters
- ciphertext: An SJCL compatible ciphertext JSON string of the secret, encoded in Base64.
- password_part_private: the private password part which was used to encrypt the secret, in Base64 format.
- description (optional): a description for the secret. Cannot be seen when viewing the secret.
- message (optional): a message for the secret. Will be shown along the secret.
- expiration (optional): an expiration time for the secret, in hours. Possible values: 0-350.
- view_button (optional): show a view secret button instead of showing the secret immediately after opening the link. To enable this feature set this to true.
- captcha (optional): show a simple CAPTCHA before showing the secret, mainly for blocking automated scanners. To enable this feature set this to true.
- password (optional): a password for the secret.
- max_views (optional): how many times the secret can be viewed. Possible values: 1-100.
Code example
Please see our API examples.
List secrets
Request type: GET
Request path: https://password.link/api/secrets
Status code of successful query: 200 OK
Fetch a list of secrets. Does not contain the ciphertexts private password parts, only IDs, descriptions and the like.
Limit and offset
The maximum amount of returned secrets for each query is limited to 50. You can control the offset with the optional offset query parameter.
For example to skip the first 50 records, use a query like: .../api/secrets?offset=50
Query example
curl -H "Authorization: ApiKey private_key_abcd" https://password.link/api/secrets
Response example
{ "data": [ { "id": the ID of the secret, "created_at": when the secret was created, "message": the message for the secret, "description": the description of the secret, "view_button": is the view secret button enabled, "captcha": is the CAPTCHA enabled, "password": does the secret have a password, "expiration": expiration time in hours, "expired": has the secret expired, "view_times": how many times the secret has beew viewed, "max_views": the maximum amount of times the secret can be viewed, "views": [ { "viewed_at": a timestamp of when the secret was viewed, "viewed_by_ip": IP address of the viewer, "viewed_by_user_agent": user agent of the viewer } ] } ], "metadata": { "secrets_total": 1, "secrets_usage": 1, "secrets_allowance": 1 } }
Delete secret
Request type: DELETE
Request path: https://password.link/api/secrets/<id>
Status code of successful query: 200 OK
Delete a secret.
Query example
curl -H "Authorization: ApiKey private_key_abcd" \ -X DELETE https://password.link/api/secrets/dT5g
Response example
{ "data": null, "metadata": { "secrets_total": 1, "secrets_usage": 1, "secrets_allowance": 1 } }
Create Secret Request
Request type: POST
Request path: https://password.link/api/secret_requests
Status code of successful query: 201 Created
Create a new Secret Request.
Request parameters
- description: description for the Secret Request.
- message: message for the Secret Request viewer.
- expiration: expiration time for the Secret Request, in hours.
- limit: usage limit for the Secret Request.
- send_request_to_email: send the created Secret Request link to the given email address.
- send_to_email: send the Secret link created using the Secret Request to the given email address.
- secret_description: description for the Secret created using the Secret Request.
- secret_message: message for the Secret created using the Secret Request.
- secret_expiration: expiration time for the Secret created using the Secret Request, in hours.
- secret_password: password for the Secret created using the Secret Request, in hours.
- secret_max_views: view limit for the Secret created using the Secret Request.
Query example
curl -H "Authorization: ApiKey private_key_abcd" \ -H "Content-Type: application/json" -X POST https://password.link/api/secret_requests
Response example
{ "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 } }
List Secret Requests
Request type: GET
Request path: https://password.link/api/secret_requests
Status code of successful query: 200 OK
List Secret Requests.
Limit and offset
The maximum amount of returned results for each query is limited to 50. You can control the offset with the optional offset query parameter.
For example to skip the first 50 records, use a query like: .../api/secret_requests?offset=50
Query example
curl -H "Authorization: ApiKey private_key_abcd" https://password.link/api/secret_requests
Response example
{ "data":[ { "id":"5e976e6e-d205-4f58-8df9-5ac0048bc702", "description":"example", "message":"example", "expiration":3, "limit":1, "send_to_email":"example@example.com", "secret_description":"example", "secret_message":"example", "secret_expiration":"example", "secret_max_views":4, "secret_password":false, "template_id":null } ], "metadata": { "secrets_total":70, "secrets_usage":25, "secrets_allowance":100, "secret_requests_total":10, "secret_requests_allowance":100 } }
Delete Secret Request
Request type: DELETE
Request path: https://password.link/api/secret_requests/<id>
Status code of successful query: 200 OK
Delete a Secret Request.
Query example
curl -H "Authorization: ApiKey private_key_abcd" \ -X DELETE https://password.link/api/secret_requests/5e976e6e-d205-4f58-8df9-5ac0048bc702
Response example
{ "data": null, "metadata": { "secrets_total":70, "secrets_usage":25, "secrets_allowance":100, "secret_requests_total":10, "secret_requests_allowance":100 } }