The API enables automated access to and management of data and services on user and account scopes. The API is REST-based with a few concessions for security and simplicity:
In order to use the API, you must define an “API Integration”. This gives you a specific unique API token code, a secret key, and allows you to configure the scope and access that will be granted to programs using your API Integration. Your account can have multiple API Integrations configured so that you can use different codes and access levels for different applications.
To create an API Integration:
Your API Integration has a number of properties that determine how it works and what you can do with it.
Text description of the API Integration for your own use.
When not enabled, the requests using this API’s codes will be rejected.
User: User-level API functions only. Also, a username/password or API token combination must be passed to gain access to these functions for a specific user.
Account: Account-level API functions. Optionally, user-level API functions can also be performed without using a username/password.
The host name that your API calls must be addressed towards. Use of other host names will be rejected by the API. The default host is “rest.luxsci.com“; you may have a different API host if you have a dedicated WebMail or API server.
Unique API Identifier passed along as part of the authentication phase of API usage.
Unique code used to verify your access to this API. This should be treated like a very sensitive password and never disclosed or saved in locations that can be viewed by end users. Access to your Token + Key can grant people access to use of your API.
Free Trial accounts have small per-minute and per-day limits that are intended “just for testing things out”.
Accounts using shared services (i.e., shared API/WebMail servers) have larger limits (e.g. 60 requests/minute; 6000 requests/day); these limits can be increased somewhat by support; however, there is a fee for that.
Accounts using dedicated servers, and which have dedicated WebMail, API, and Private Labeling can have their API processed through their own dedicated server; in this case, the API limits can be made very much higher.
Please contact support to inquire about changing your API limits.
(See the section on Access Controls, below)
If you create a program that uses your API, you must be very careful of who can access the API Key and Token! E.g., if you create an application and distribute it, people could garner your Key and Token from the API code and then use your API Integration to do whatever your API is allowed to do. This is a shortcoming of any API.
We have some specific recommendations for you:
There are many layers of access controls built into the API. In order for your API requests to function at all:
Additionally, you can control access to your API and the functionality of your API in the Access Control area of your API Interface configuration/ edit screen.
The first layer is the IP Address Allow List. This is a list of individual IP Addresses (e.g. 4.2.2.1) or CIDR blocks (e.g. 4.2.2.1/24). When editing your allow list, you can delimit the entries with new lines, spaces, and commas.
Here is how it works:
You can optionally select specific users in your account that will be protected from the API. I.e.,
User protection is appropriate when you have certain important or administrative users that you want to exclude from API access, or when you do not fully trust your API client.
Each API scope contains a number of commands. The API provides opt-in access to these commands (for the most part – some read-only operations that do not involve sensitive data — are available generally). This allows you to be very specific about what commands your API can perform and protects you from your API “gaining unwanted access” in the future just because new commands have been added to the API.
Please refer to the API documentation for each level of scope to see what sets of commands can be opted into by your API.
All API requests, except authentication and authentication revocation, take place in a “scope” with is either “user” or “account”.
An API Integration whose “scope” is set to “user” must send user authentication information (i.e., username and password) as part of the authentication request. This authentication codes returned can then be only used for user scope commands for the user authenticated. You can use application-specific usernames that have API access (e.g., user@domain.com/api-access) if you have created such in the user security settings pages.
This method of access is appropriate when your application is distributed and you cannot ensure that your API Key cannot be discovered. API calls thus require both that key and the user’s credentials.
This method is also appropriate when you will know the user’s authentication credentials.
All user requests have API URLS that start with: /perl/v2/api/user/[username] where “username” is the login email address (e.g. “joe@domain.com”) of the user with respect to whom the command will apply. The “username” can also be just the user’s unique ID number. Note, while you may use an application-specific username and password (e.g., user@domain.com/api- access) for authentication, the “[username]” in the URL must always be the canonical username (e.g., user@domain.com) or unique ID number.
An API Integration whose “scope” is set to “account” and where you have enabled “Permit user-level commands without username and password” in your API access control settings can also access user-scope commands. In this case, you do not need the user’s authentication credentials and you API client, once authenticated, can make user- scope requests for any permitted user without needing to re-authenticate to change user or scope.
This is appropriate when designing API clients that will manage your account or accounts in an automated manner and where your API Key can be kept safe.
API Integrations explicitly allow one of:
The API endpoint URLs for user and account scope commands differ. This table shows the difference. Note that the rest.luxsci.com hostname used in the examples may be different for your account.
https://rest.luxsci.com/perl/api/v2/user/[email]/…
[email] will be the login username/email address of the user in question.
https://rest.luxsci.com/perl/api/v2/account/[account_id]/…
[account_id] is the LuxSci account number for the account in question.
You can skip this section if you are using an SDK. This section provides detailed documentation on the proper way to program your API clients to make API calls to the LuxSci API, how to authenticate, how to invalidate your API session, and how to make calls containing file attachments.
Here are the quick specifics you should know about all API calls:
The HTTP responses include the following response headers:
application/json
The maximum number of additional requests permitted during the current 1-minute window before a “429” error will be returned.
A timestamp of the “next minute,” specified as seconds-since-epoch. I.e., at this time, your “X-RateLimit-Remaining” will reset to the value of “X-RateLimit-Limit” allowing more API requests.
All API calls will return a response with a JSON body (and content type “application/json”). These responses can all include the following keywords:
Value will be “1” on success; “0” on failure.
Appears only in error responses (where success=0). This is a plain text description of the error.
Optional plain text message that can occur in successful requests (success=1). This is usually only present if the data keyword is omitted / not needed.
Error responses for all API commands will have a consistent format. The HTTP Status code will be somewhere from 400 to 599, where the code number corresponds to the error type. The response body will be standard JSON with the “success” keyword set to “0” and the “error_message” keyword containing a plain text description of the reason for the failure.
Note that it is possible that in some cases the JSON error body would be missing; e.g. in situations where the error involved is unrelated to the API itself and so the API is not involved in the request and cannot return a standard error format. Examples of this could include cases 503 errors from a server being unavailable, bad gateway errors related to proxy load balancers, etc.
Note that Unicode and other characters can be embedded in double quoted strings in JSON response bodies. These should be properly parsed when the response body is converted from plain text JSON to an actual object in your code. Examples of common embedded characters include “\n” (for linefeed), “u0073” (for the letter “s” … to prevent the word “script” from showing up in the response, as that can trigger issues with filters). For example you may see in a raw response the string “de u0073cription”. Parsed, this becomes the string “description” – but the “s” is quoted in the raw response to limit the appearance of the raw text “script” … which could trigger content filters.
{“auth”:”965823916111409-1426025141-b3486 705691ba0bd15e31292″ + “166e3494034c748cb3fdfed0b9d456c647012763″,”success”:1}
{“success”:0,”error_message”:”Invalid authentication credentials.”}
In order to use any API commands, at any level, your client must first authenticate and obtain an authentication code. This authentication code can then be used to make one or more calls to API functions. Your authentication “session” can also be revoked, immediately invalidating all authentication codes received for it (e.g. this is a “log out”).
In order to authenticate, you will need your API Token, API Key, and your API Host name. This API request is different from authenticated requests in that you do not need to send a cookie, and the way that the request is signed is different.
POST
None
/perl/api/v2/auth
None
Possible JSON object keywords:
Standard JSON response. No “data” keyword will be sent. See the “auth” keyword for your new authentication token.
POST https://rest.luxsci.com/perl/api/v2/auth
Content-Type: application/json
{ “token”: “pJsvioyq8LvtIthmqn8k1u4z0wbpnKwqotupx5DB1aM”, “date”:”1426025141″, “signature”: “1428c39c8d1893e4cab65181e6fe09ca36c3a18b5718c1df79b97f24c0c92c6e” }
HTTP/1.1 201 Created
Content-Type: application/json
Pragma: no-cache
Server: Apache
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: 1668889680
{“auth”:”965823916111409-1426025141-b3486705691ba0bd15e31292″ + “166e3494034c-748cb3fdfed0b9d456c647012763″,”success”:1}
Authenticated API requests include all non-authentication requests. These work similarly to authentication requests, described above, except that you must also send along a cookie named “signature”. This cookie validates the request. The content of this cookie is defined as follows:
signature: auth_code:signature_code
auth_code: a currently valid authorization code received from an Authorization API call, or from another successful recent API call.
signature_code: HMAC( text_to_sign, API Key)
text_to_sign: auth_code + “\n” + request_method + “\n” + request_path + “\n” + query_string + “\n” + request_body_hash + “\n”
request_method: the HTTP request method being used, in all upper case. E.g. “GET” or “POST” or “DELETE”
request_path: The portion of the request URL after the protocol and hostname, but before the ? and query string, if any. E.g. “/perl/api/v2/auth”
query_string: The portion of the request URL after the “?”. If you are not making a request that includes a query string, then you should treat this value as an empty string.
request_body_hash: If your request does not include a JSON request body, then you should treat this value as an empty string. Otherwise it is a SHA 256 Digest of the complete JSON request body:
request_body_hash: SHA_256_HEX( Trimmed JSON_Request_Body )
Trimmed JSON Request Body: the raw JSON Request Body content in the request with all leading and training white spaces removed (e.g. spaces, tabs, carriage returns, and line feeds before and after the actual JSON content).
For an example of this, see the next section: Authentication Revocation Requests.
To revoke your authentication session and invalidate all authorization codes received, you need to send an authenticated API request as follows:
Method DELETE
Required
/perl/api/v2/auth
None
None
Authentication request
POST https://rest.luxsci.com/perl/api/v2/auth
User-Agent: Doctor
Content-Type: application/json
{“signature”:”67e2873a262d64bbdf06dacee633698683362df81b979c30b3f063dd1738c9a6″,”date”: “1426087957”,”token”:”pJsvioyq8LvtIthmqn8k1u4z0wbpnKwqotupx5DB1aM”}
Note: signature = HMAC( “pJsvioyq8LvtIthmqn8k1u4z0wbpnKwqotupx5DB1aM” + “\n” + “1426087957” + “\n”, API_KEY)
Success response
HTTP/1.1 201 Created
Pragma: no-cache
Content-Type: application/json
{“auth”:”151-1426087958-34ca90493592726104b237e98d8129fe8626f181e38f502fa2b99dc066e72298″,”success”:1}
Authentication Revocation
DELETE https://rest.luxsci.com/perl/api/v2/auth
Cookie: signature=151-1426087958-34ca90493592726104b237e98d8129fe8626f181e38f502fa2b9 9dc066e72298:fd66fc402b9c58f136105d768225a67dec4b8eeb756743bbca35c2caca0fd57f
Note: signature = “151-1426087958-34ca90493592726104b237e98d8129fe8626f181e38f502fa2b99dc066e72298” + “:” + signature_code
signature_code = HMAC(“151-1426087958-34ca90493592726104b237e98d8129fe8626f181e38f5 02fa2b99dc066e72298” + “\n” + “DELETE” + “\n” + “/perl/api/v2/auth” + “\n” + “” + “\n” + “” + “\n”, API_KEY)
Successful revocation
HTTP/1.1 200 OK
Pragma: no-cache
Content-Type: application/json
{“success”:1,”comment”:”Authentication session revoked.”}
Some authenticated API requests allow you to include file attachments. When including files in your POST or PUT request, the HTTP syntax of the request is different: it uses a “multipart/form-data” content type instead of an “application/json” content type.
In particular:
Here is an example SecureLine Send request that includes a simple text file as an attachment. The signature cookie is truncated to save space.
POST https://rest.luxsci.com/perl/api/v2/user/user@domain.com/email/compose/secureline/send
Content-Type: multipart/form-data; boundary=—————–LUXSCI-363789.496459765—
Cookie: signature=1623-1454003053-…a36d376c86313fbf65d8a
——————-LUXSCI-363789.496459765—
Content-Disposition: form-data; name=”json”; filename=”json.js”
Content-Type: application/json
{“attachments”:[{“hash”:”975867324207d82a1d1e01fa2b6e582907756e737aa7771d92b17609e41 bce16″,”name”:”test-attachment.txt”}],”from_address”:”bob@doctorbob.com”,”subject”:”SecureLine message test”,”no_tls_only”:1,”body”:”Message body”,”to”:[“user@test-domain.com”],”from_name”:”Dr. Bob”,”receipt”:1,”body_type”:”text”}
——————-LUXSCI-363789.496459765—
Content-Disposition: form-data; name=”files”; filename=”test-attachment.txt”
Content-Type: text/plain
File Content!!
——————-LUXSCI-363789.496459765—–
NOTE: If you are crafting these requests by hand, remember that you must use “\r\n” (i.e. char(13) char(10) ) as line terminators at the ends of the boundaries, the MIME headers, and blank spacer lines between MIME headers and your raw/binary attachment content.
The LuxSci REST API uses standard HTTP status codes to indicate the success or failure of requests. The codes commonly returned by the API and their meanings are below. In many cases, the API will also return a JSON object with a descriptive error string which provides more specific information.