Co-authored-by: Adrià Casajús <adria.casajus@proton.ch>
26 KiB
API
- POST /api/auth/login: Authentication
- POST /api/auth/mfa: 2FA authentication
- POST /api/auth/facebook (deprecated)
- POST /api/auth/google (deprecated)
- POST /api/auth/register: Register a new account.
- POST /api/auth/activate: Activate new account.
- POST /api/auth/reactivate: Request a new activation code.
- POST /api/auth/forgot_password: Request reset password link.
- GET /api/user_info: Get user's information.
- PATCH /api/sudo: Enable sudo mode.
- DELETE /api/user: Delete the current user.
- PATCH /api/user_info: Update user's information.
- POST /api/api_key: Create a new API key.
- GET /api/logout: Log out.
- GET /api/v5/alias/options: Get alias options. Used by create alias process.
- POST /api/v3/alias/custom/new: Create new alias.
- POST /api/alias/random/new: Random an alias.
- GET /api/v2/aliases: Get user's aliases.
- GET /api/aliases/:alias_id: Get alias information.
- DELETE /api/aliases/:alias_id: Delete an alias.
- POST /api/aliases/:alias_id/toggle: Enable/disable an alias.
- GET /api/aliases/:alias_id/activities: Get alias activities.
- PATCH /api/aliases/:alias_id: Update alias information.
- GET /api/aliases/:alias_id/contacts: Get alias contacts.
- POST /api/aliases/:alias_id/contacts: Create a new contact for an alias.
- POST /api/mailboxes: Create a new mailbox.
- DELETE /api/mailboxes/:mailbox_id: Delete a mailbox.
- PUT /api/mailboxes/:mailbox_id: Update a mailbox.
- GET /api/custom_domains: Get custom domains.
- PATCH /api/custom_domains/:custom_domain_id: Update custom domain's information.
- GET /api/custom_domains/:custom_domain_id/trash: Get deleted aliases of a custom domain.
- DELETE /api/contacts/:contact_id: Delete a contact.
- POST /api/contacts/:contact_id/toggle: Block/unblock a contact.
- GET /api/notifications: Get notifications.
- POST /api/notifications/:notification_id: Mark as read a notification.
- GET /api/setting: Get user's settings.
- PATCH /api/setting: Update user's settings.
- GET /api/v2/setting/domains: Get domains that user can use to create random alias.
- GET /api/export/data: Export user's data.
- GET /api/export/aliases: Export aliases into a CSV.
- POST /api/apple/process_payment: Process Apple's receipt.
- GET /api/phone/reservations/:reservation_id: Get messages received during a reservation.
SimpleLogin current API clients are Chrome/Firefox/Safari extension and mobile (iOS/Android) app. These clients rely
on API Code
for authentication.
Once the Api Code
is obtained, either via user entering it (in Browser extension case) or by logging in (in Mobile
case), the client includes the api code
in Authentication
header in almost all requests.
For some endpoints, the hostname
should be passed in query string. hostname
is the the URL hostname (
cf https://en.wikipedia.org/wiki/URL), for ex if URL is http://www.example.com/index.html then the hostname
is www.example.com
. This information is important to know where an alias is used in order to suggest user the same
alias if they want to create on alias on the same website in the future.
If error, the API returns 4** with body containing the error message, for example:
{
"error": "request body cannot be empty"
}
The error message could be displayed to user as-is, for example for when user exceeds their alias quota. Some errors
should be fixed during development however: for example error like request body cannot be empty
is there to catch
development error and should never be shown to user.
All following endpoint return 401
status code if the API Key is incorrect.
Account endpoints
POST /api/auth/login
Input:
- password
- device: device name. Used to create the API Key. Should be humanly readable so user can manage later on the "API Key" page.
Output:
- name: user name, could be an empty string
- email: user email
- mfa_enabled: boolean
- mfa_key: only useful when user enables MFA. In this case, user needs to enter their OTP token in order to login.
- api_key: if MFA is not enabled, the
api key
is returned right away.
The api_key
is used in all subsequent requests. It's empty if MFA is enabled. If user hasn't enabled MFA, mfa_key
is
empty.
Return 403 if user has enabled FIDO. The client can display a message to suggest user to use the API Key
instead.
POST /api/auth/mfa
Input:
- mfa_token: OTP token that user enters
- mfa_key: MFA key obtained in previous auth request, e.g. /api/auth/login
- device: the device name, used to create an ApiKey associated with this device
Output:
- name: user name, could be an empty string
- api_key: if MFA is not enabled, the
api key
is returned right away. - email: user email
The api_key
is used in all subsequent requests. It's empty if MFA is enabled. If user hasn't enabled MFA, mfa_key
is
empty.
POST /api/auth/facebook
Input:
- facebook_token: Facebook access token
- device: device name. Used to create the API Key. Should be humanly readable so user can manage later on the "API Key" page.
Output: Same output as for /api/auth/login
endpoint
POST /api/auth/google
Input:
- google_token: Google access token
- device: device name. Used to create the API Key. Should be humanly readable so user can manage later on the "API Key" page.
Output: Same output as for /api/auth/login
endpoint
POST /api/auth/register
Input:
- password
Output: 200 means user is going to receive an email that contains an activation code. User needs to enter this code to confirm their account -> next endpoint.
POST /api/auth/activate
Input:
- code: the activation code
Output:
- 200: account is activated. User can login now
- 400: wrong email, code
- 410: wrong code too many times. User needs to ask for an reactivation -> next endpoint
POST /api/auth/reactivate
Input:
Output:
- 200: user is going to receive an email that contains the activation code.
POST /api/auth/forgot_password
Input:
Output: always return 200, even if email doesn't exist. User need to enter correctly their email.
GET /api/user_info
Given the API Key, return user name and whether user is premium. This endpoint could be used to validate the api key.
Input:
Authentication
header that contains the api key
Output: if api key is correct, return a json with user name and whether user is premium, for example:
{
"name": "John Wick",
"is_premium": false,
"email": "john@wick.com",
"in_trial": true,
"profile_picture_url": "https://profile.png"
}
If api key is incorrect, return 401.
PATCH /api/user_info
Update user info
Input:
- profile_picture: the profile picture in base64. Setting to
null
remove the current profile picture. - name
Output: same as GET /api/user_info
PATCH /api/sudo
Enable sudo mode
Input:
Authentication
header that contains the api key- password: User password to validate the user presence and enter sudo mode
{
"password": "yourpassword"
}
Output:
- 200 with
{"ok": true}
if sudo mode has been enabled. - 403 with
{"error": "Some error"}
if there is an error.
DELETE /api/user
Delete the current user. It requires sudo mode.
Input:
Authentication
header that contains the api key
Output:
- 200 with
{"ok": true}
if account is scheduled to be deleted. - 440 with
{"error": "Need sudo"}
if sudo mode is not enabled. - 403 with
{"error": "Some error"}
if there is an error.
POST /api/api_key
Create a new API Key
Input:
Authentication
header that contains the api key- Or the correct cookie is set, i.e. user is already logged in on the web
- device: device's name
Output
- 401 if user is not authenticated
- 201 with the
api_key
{
"api_key": "long string"
}
GET /api/logout
Log user out
Input:
Authentication
header that contains the api key- Or the correct cookie is set, i.e. user is already logged in on the web
Output:
- 401 if user is not authenticated
- 200 if success
Alias endpoints
GET /api/v5/alias/options
User alias info and suggestion. Used by the first extension screen when user opens the extension.
Input:
Authentication
header that contains the api key- (Optional but recommended)
hostname
passed in query string.
Output: a json with the following field:
- can_create: boolean. Whether user can create new alias
- suffixes: list of alias suffix that user can use.
Each item is a dictionary with
suffix
,signed-suffix
,is_custom
,is_premium
as keys. Thesigned-suffix
is necessary to avoid request tampering. - prefix_suggestion: string. Suggestion for the
alias prefix
. Usually this is the website name extracted fromhostname
. If nohostname
, then theprefix_suggestion
is empty. - recommendation: optional field, dictionary. If an alias is already used for this website, the recommendation will be
returned. There are 2 subfields in
recommendation
:alias
which is the recommended alias andhostname
is the website on which this alias is used before.
For ex:
{
"can_create": true,
"prefix_suggestion": "test",
"suffixes": [
{
"signed_suffix": ".cat@d1.test.X6_7OQ.0e9NbZHE_bQvuAapT6NdBml9m6Q",
"suffix": ".cat@d1.test",
"is_custom": true,
"is_premium": false
},
{
"signed_suffix": ".chat@d2.test.X6_7OQ.TTgCrfqPj7UmlY723YsDTHhkess",
"suffix": ".chat@d2.test",
"is_custom": false,
"is_premium": false
},
{
"signed_suffix": ".yeah@sl.local.X6_7OQ.i8XL4xsMsn7dxDEWU8eF-Zap0qo",
"suffix": ".yeah@sl.local",
"is_custom": true,
"is_premium": false
}
]
}
POST /api/v3/alias/custom/new
Create a new custom alias.
Input:
Authentication
header that contains the api key- (Optional but recommended)
hostname
passed in query string - Request Message Body in json (
Content-Type
isapplication/json
)- alias_prefix: string. The first part of the alias that user can choose.
- signed_suffix: should be one of the suffixes returned in the
GET /api/v4/alias/options
endpoint. - mailbox_ids: list of mailbox_id that "owns" this alias
- (Optional) note: alias note
- (Optional) name: alias name
Output: If success, 201 with the new alias info. Use the same format as in GET /api/aliases/:alias_id
POST /api/alias/random/new
Create a new random alias.
Input:
Authentication
header that contains the api key- (Optional but recommended)
hostname
passed in query string - (Optional) mode: either
uuid
orword
. By default, use the user setting when creating new random alias. - Request Message Body in json (
Content-Type
isapplication/json
)- (Optional) note: alias note
Output: If success, 201 with the new alias info. Use the same format as in GET /api/aliases/:alias_id
GET /api/v2/aliases
Get user aliases.
Input:
Authentication
header that contains the api keypage_id
in query. Used for the pagination. The endpoint returns maximum 20 aliases for each page.page_id
starts at 0.- (Optional)
pinned
in query. If set, only pinned aliases are returned. - (Optional)
disabled
in query. If set, only disabled aliases are returned. - (Optional)
enabled
in query. If set, only enabled aliases are returned. Please notepinned
,disabled
,enabled
are exclusive, i.e. only one can be present. - (Optional) query: included in request body. Some frameworks might prevent GET request having a non-empty body, in this case this endpoint also supports POST.
Output: If success, 200 with the list of aliases. Each alias has the following fields:
- id
- name
- enabled
- creation_timestamp
- note
- nb_block
- nb_forward
- nb_reply
- support_pgp: whether an alias can support PGP, i.e. when one of alias's mailboxes supports PGP.
- disable_pgp: whether the PGP is disabled on this alias. This field should only be used when
support_pgp
is true. By settingdisable_pgp=true
, a user can explicitly disable PGP on an alias even its mailboxes support PGP. - mailbox: obsolete, should use
mailboxes
instead.- id
- mailboxes: list of mailbox, contains at least 1 mailbox.
- id
- (nullable) latest_activity:
- action: forward|reply|block|bounced
- timestamp
- contact:
- name
- reverse_alias
- pinned: whether an alias is pinned
Here's an example:
{
"aliases": [
{
"creation_date": "2020-04-06 17:57:14+00:00",
"creation_timestamp": 1586195834,
"email": "prefix1.cat@sl.local",
"name": "A Name",
"enabled": true,
"id": 3,
"mailbox": {
"email": "a@b.c",
"id": 1
},
"mailboxes": [
{
"email": "m1@cd.ef",
"id": 2
},
{
"email": "john@wick.com",
"id": 1
}
],
"latest_activity": {
"action": "forward",
"contact": {
"email": "c1@example.com",
"name": null,
"reverse_alias": "\"c1 at example.com\" <re1@SL>"
},
"timestamp": 1586195834
},
"nb_block": 0,
"nb_forward": 1,
"nb_reply": 0,
"note": null,
"pinned": true
}
]
}
GET /api/aliases/:alias_id
Get alias info
Input:
Authentication
header that contains the api keyalias_id
in url
Output: Alias info, use the same format as in /api/v2/aliases. For example:
{
"creation_date": "2020-04-06 17:57:14+00:00",
"creation_timestamp": 1586195834,
"email": "prefix1.cat@sl.local",
"name": "A Name",
"enabled": true,
"id": 3,
"mailbox": {
"email": "a@b.c",
"id": 1
},
"mailboxes": [
{
"email": "m1@cd.ef",
"id": 2
},
{
"email": "john@wick.com",
"id": 1
}
],
"latest_activity": {
"action": "forward",
"contact": {
"email": "c1@example.com",
"name": null,
"reverse_alias": "\"c1 at example.com\" <re1@SL>"
},
"timestamp": 1586195834
},
"nb_block": 0,
"nb_forward": 1,
"nb_reply": 0,
"note": null,
"pinned": true
}
DELETE /api/aliases/:alias_id
Delete an alias
Input:
Authentication
header that contains the api keyalias_id
in url.
Output: If success, 200.
{
"deleted": true
}
POST /api/aliases/:alias_id/toggle
Enable/disable alias
Input:
Authentication
header that contains the api keyalias_id
in url.
Output: If success, 200 along with the new alias status:
{
"enabled": false
}
GET /api/aliases/:alias_id/activities
Get activities for a given alias.
Input:
Authentication
header that contains the api keyalias_id
: the alias id, passed in url.page_id
used in request query (?page_id=0
). The endpoint returns maximum 20 aliases for each page.page_id
starts at 0.
Output: If success, 200 with the list of activities, for example:
{
"activities": [
{
"action": "reply",
"from": "yes_meo_chat@sl.local",
"timestamp": 1580903760,
"to": "marketing@example.com",
"reverse_alias": "\"marketing at example.com\" <reply@a.b>",
"reverse_alias_address": "reply@a.b"
}
]
}
PATCH /api/aliases/:alias_id
Update alias info.
Input:
Authentication
header that contains the api keyalias_id
in url.- (optional)
note
in request body - (optional)
mailbox_id
in request body - (optional)
name
in request body - (optional)
mailbox_ids
in request body: array of mailbox_id - (optional)
disable_pgp
in request body: boolean - (optional)
pinned
in request body: boolean
Output: If success, return 200
GET /api/aliases/:alias_id/contacts
Get contacts for a given alias.
Input:
Authentication
header that contains the api keyalias_id
: the alias id, passed in url.page_id
used in request query (?page_id=0
). The endpoint returns maximum 20 contacts for each page.page_id
starts at 0.
Output: If success, 200 with the list of contacts, for example:
{
"contacts": [
{
"id": 1,
"contact": "marketing@example.com",
"creation_date": "2020-02-21 11:35:00+00:00",
"creation_timestamp": 1582284900,
"last_email_sent_date": null,
"last_email_sent_timestamp": null,
"reverse_alias": "marketing at example.com <reply+bzvpazcdedcgcpztehxzgjgzmxskqa@sl.co>",
"block_forward": false
},
{
"id": 2,
"contact": "newsletter@example.com",
"creation_date": "2020-02-21 11:35:00+00:00",
"creation_timestamp": 1582284900,
"last_email_sent_date": "2020-02-21 11:35:00+00:00",
"last_email_sent_timestamp": 1582284900,
"reverse_alias": "newsletter at example.com <reply+bzvpazcdedcgcpztehxzgjgzmxskqa@sl.co>",
"reverse_alias_address": "reply+bzvpazcdedcgcpztehxzgjgzmxskqa@sl.co",
"block_forward": true
}
]
}
Please note that last_email_sent_timestamp and last_email_sent_date can be null.
POST /api/aliases/:alias_id/contacts
Create a new contact for an alias.
Input:
Authentication
header that contains the api keyalias_id
in url.contact
in request body
Output: If success, return 201.
Return 200 and existed=true
if contact is already added.
{
"id": 1,
"contact": "First Last <first@example.com>",
"creation_date": "2020-03-14 11:52:41+00:00",
"creation_timestamp": 1584186761,
"last_email_sent_date": null,
"last_email_sent_timestamp": null,
"reverse_alias": "First Last first@example.com <ra+qytyzjhrumrreuszrbjxqjlkh@sl.local>",
"reverse_alias_address": "reply+bzvpazcdedcgcpztehxzgjgzmxskqa@sl.co",
"existed": false
}
It can return 403 with an error if the user cannot create reverse alias.
``json { "error": "Please upgrade to create a reverse-alias" }
### Mailbox endpoints
#### GET /api/v2/mailboxes
Get user's mailboxes, including unverified ones.
Input:
- `Authentication` header that contains the api key
Output:
List of mailboxes. Each mailbox has id, email, default, creation_timestamp field
```json
{
"mailboxes": [
{
"email": "a@b.c",
"id": 1,
"default": true,
"creation_timestamp": 1590918512,
"nb_alias": 10,
"verified": true
},
{
"email": "m1@example.com",
"id": 2,
"default": false,
"creation_timestamp": 1590918512,
"nb_alias": 0,
"verified": false
}
]
}
Mailbox endpoints
POST /api/mailboxes
Create a new mailbox
Input:
Authentication
header that contains the api key- email: the new mailbox address
Output:
- 201 along with the following response if new mailbox is created successfully. User is going to receive a verification
email.
- id: integer
- email: the mailbox email address
- verified: boolean.
- default: whether is the default mailbox. User cannot delete the default mailbox
- 400 with error message otherwise. The error message can be displayed to user.
DELETE /api/mailboxes/:mailbox_id
Delete a mailbox. User cannot delete the default mailbox
Input:
Authentication
header that contains the api keymailbox_id
: in url
Output:
- 200 if deleted successfully
- 400 if error
PUT /api/mailboxes/:mailbox_id
Update a mailbox.
Input:
Authentication
header that contains the api keymailbox_id
: in url- (optional)
default
: boolean. Set a mailbox as default mailbox. - (optional)
email
: email address. Change a mailbox email address. - (optional)
cancel_email_change
: boolean. Cancel mailbox email change.
Output:
- 200 if updated successfully
- 400 if error
Custom domain endpoints
GET /api/custom_domains
Return user's custom domains
Input:
Authentication
header that contains the api key
Output: List of custom domains.
[
{
"catch_all": false,
"creation_date": "2021-03-10 21:36:08+00:00",
"creation_timestamp": 1615412168,
"domain_name": "test1.org",
"id": 1,
"is_verified": true,
"mailboxes": [
{
"email": "a@b.c",
"id": 1
}
],
"name": null,
"nb_alias": 0,
"random_prefix_generation": false
},
{
"catch_all": false,
"creation_date": "2021-03-10 21:36:08+00:00",
"creation_timestamp": 1615412168,
"domain_name": "test2.org",
"id": 2,
"is_verified": false,
"mailboxes": [
{
"email": "a@b.c",
"id": 1
}
],
"name": null,
"nb_alias": 0,
"random_prefix_generation": false
}
]
PATCH /api/custom_domains/:custom_domain_id
Update custom domain's information
Input:
Authentication
header that contains the api keycustom_domain_id
in url.- (optional)
catch_all
: boolean, in request body - (optional)
random_prefix_generation
: boolean, in request body - (optional)
name
: text, in request body - (optional)
mailbox_ids
: array of mailbox id, in request body
Output: If success, return 200 along with updated custom domain
GET /api/custom_domains/:custom_domain_id/trash
Get deleted alias for a custom domain
Input:
Authentication
header that contains the api key
Output: List of deleted alias.
{
"aliases": [
{
"alias": "first@test1.org",
"deletion_timestamp": 1605464595
}
]
}
Contact endpoints
DELETE /api/contacts/:contact_id
Delete a contact
Input:
Authentication
header that contains the api keycontact_id
in url.
Output: If success, 200.
{
"deleted": true
}
POST /api/contacts/:contact_id/toggle
Block/unblock contact
Input:
Authentication
header that contains the api keycontact_id
in url.
Output: If success, 200 along with the new alias status:
{
"block_forward": false
}
Notification endpoints
GET /api/notifications
Get notifications
Input:
Authentication
in header: the api key- page in url: the page number, starts at 0
Output:
- more: whether there's more notifications
- notifications: list of notification, each notification has:
- id
- message: the message in html
- title: the message title
- read: whether the user has read the notification
- created_at: when the notification is created
For example
{
"more": false,
"notifications": [
{
"created_at": "2 minutes ago",
"id": 1,
"message": "Hey!",
"read": false
}
]
}
POST /api/notifications/:notification_id
Mark a notification as read
Input:
Authentication
in header: the api key- notification_id in url: the page number, starts at 0
Output: 200 if success
Settings endpoints
GET /api/setting
Return user setting.
{
"alias_generator": "word",
"notification": true,
"random_alias_default_domain": "sl.local",
"sender_format": "AT",
"random_alias_suffix": "random_string"
}
PATCH /api/setting
Update user setting. All input fields are optional.
Input:
- alias_generator (string):
uuid
orword
- notification (boolean):
true
orfalse
- random_alias_default_domain (string): one of the domains returned by
GET /api/setting/domains
- sender_format (string): possible values are
AT
,A
,NAME_ONLY
,AT_ONLY
,NO_NAME
- random_alias_suffix (string): possible values are
word
,random_string
Output: same as GET /api/setting
GET /api/v2/setting/domains
Return domains that user can use to create random alias
is_custom
is true if this is a user's domain, otherwise false.
[
{
"domain": "d1.test",
"is_custom": false
},
{
"domain": "d2.test",
"is_custom": false
},
{
"domain": "sl.local",
"is_custom": false
},
{
"domain": "ab.cd",
"is_custom": true
}
]
Import and export endpoints
GET /api/export/data
Export user data
Input:
Authentication
in header: the api key
Output: Alias, custom domain and app info
GET /api/export/aliases
Export user aliases in an importable CSV format
Input:
Authentication
in header: the api key
Output: A CSV file with alias information that can be imported in the settings screen
Misc endpoints
POST /api/apple/process_payment
Process payment receipt
Input:
Authentication
in header: the api keyreceipt_data
in body: the receipt_data base64Encoded returned by StoreKit, i.e.rawReceiptData.base64EncodedString
- (optional)
is_macapp
in body: if this field is present, the request is sent from the MacApp (Safari Extension) and not iOS app.
Output: 200 if user is upgraded successfully 4** if any error.
Phone endpoints
GET /api/phone/reservations/:reservation_id
Get messages received during a reservation.
Input:
Authentication
in header: the api keyreservation_id
Output: List of messages for this reservation and whether the reservation is ended.
{
"ended": false,
"messages": [
{
"body": "body",
"created_at": "just now",
"from_number": "from_number",
"id": 7
}
]
}