API

Your API key: n/a (you will see your API key after logging in)

API URL: https://api.password.link/v1

The API works over the HTTPS protocol, using the POST request type. All responses are in JSON.

Each API action costs one API unit.

Sections:
List all stored secrets | View details of a stored secret | Storing a secret | Errors

List all stored secrets

HTTPS POST parameters:

ParameterDescription
api_keyYour API key. Required.
api_commandSet to "list_all". Required.

Usage example

A simple usage example using the command line tool curl.

curl -X POST -F 'api_key=YOUR_API_KEY' \
-F 'api_command=list_all' https://api.password.link/v1
			

Response example

{"result":"success","password_list":[
{"password_id":"id1","created_at":"2017-01-01 00:00:00"},
{"password_id":"id2","created_at":"2017-01-01 00:00:00"}]}
			

View details of a stored secret

HTTPS POST parameters:

ParameterDescription
api_keyYour API key. Required.
api_commandSet to "get_details". Required.
password_idThe ID of the secret in question. Required.

Usage example

A simple usage example using the command line tool curl.

curl -X POST -F 'api_key=YOUR_API_KEY' \
-F 'api_command=get_details' -F 'password_id=ejbV' https://api.password.link/v1
			

Response example

{"result":"success","details":{"password_id":"ejbV",
"created_at":"2017-01-01 00:00:00",
"viewed_at":"2017-01-01 00:00:00",
"description":description_if_set,
"message":message_if_set}
			

Storing a secret

HTTPS POST parameters:

ParameterDescription
api_keyYour API key. Required.
api_commandSet to "store". Required.
ciphertextAn SJCL compatible ciphertext JSON string of the secret, encoded in Base64. Required.
password_part_privateThe "private part" of the password used to encrypt the secret, encoded in Base64. Required.
descriptionDescription for the secret. Optional.
messageA message to be shown along with the secret. Optional.

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.

Creating the encryption password

The password which is used to encrypt the secret in AES must consist of two 18 character long strings. The first string, called "private part", is Base64-encoded and sent over to our API and stored into our database, and the second string, called "public part", is Base64-encoded and added into the unique password link. Use the concatenation of these two strings ("private part"+"public part") as the password for encrypting the password in AES.

EXAMPLE
Password used in AES encryption: fkgjbnvlakwiejgutnFIGKEOTIRUBNAKQJRL
=> Private part: fkgjbnvlakwiejgutn
=> Public part: FIGKEOTIRUBNAKQJRL
			

Required 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: min. 1000 (SJCL setting: "iter:1000")

Responses

All responses are in JSON format.

KeyDescription
resultAPI command result. On successful query: "success", on error: "error".
errorOn error, contains an error message. Example: "invalid_query".
password_idOn successful query, the ID of the secret. Example: "h3Kq"

Response example

{"result":"success","password_id":"p0dy"}
			

Example in Ruby

Below is an example written in the Ruby language using the Gibberish encryption library:

require "gibberish"
require "net/http"
require "uri"
require "base64"
require "json"
require "securerandom"

# A function to generate a random string with default length of 18 chars
def generate_string(l=18)
	chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
	str = ""
	l.times { str << chars[rand(chars.size)] }
	str
end

# Create the private password part and also it's Base64 encoded version
password_part_private = generate_string(18)
password_part_private_base64 = Base64.strict_encode64(password_part_private)

# Create the public password part and also it's Base64 encoded version
password_part_public = generate_string(18)
password_part_public_base64 = Base64.strict_encode64(password_part_public)

# The full password used for encryption
full_password = password_part_private + password_part_public

# Create the SJCL compatible ciphertext using Gibberish, encode it in Base64
cipher = Gibberish::AES.new(full_password, { "mode": "gcm", "ks": 256, "iter": 1000 })
ciphertext = cipher.encrypt("the_secret_password_to_be_delivered_securely")
ciphertext_base64 = Base64.strict_encode64(ciphertext)

# Send the data over to password.link API
uri = URI.parse("https://api.password.link/v1")
response = Net::HTTP.post_form(uri,
{
	"api_key" => "API_KEY",
	"api_command" => "store",
	"password_part_private" => password_part_private_base64,
	"ciphertext" => ciphertext_base64
})

# Parse the JSON result: print error if it exists,
# otherwise print the full password link
json = JSON.parse(response.body)
if json["result"] == "error"
	print "Error: " + json["error"]
else
	print "Password link: https://password.link/" +
	json["password_id"] +
	"/#" +
	password_part_public_base64
end
			

Errors

All error responses use the following format:

{"result":"error","error":"error_message"}