Getting Started
The Shareworks Public API is organized around REST. The Shareworks Public API has predictable resource-oriented URLs, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs. A development environment is provided for the testing of client API applications. The development environment does not affect live data or interact with the banking networks.
The Shareworks Public API Environments
Development
https://sum-qa02.shareworks.com/
Production
https://shareworks-api.solium.com/
Setup For API Access
To access the Shareworks Public API in either the development or production environments requires some initial setup. First, you will need to request access to the environment and provide Shareworks with the IP address of the API client machines that will be submitting requests to that environment. Shareworks will "whitelist" the IP addresses so that HTTP traffic from those IP address is allowed into the environment. Shareworks will also create an API administrator account and provide you with the account credentials. You will then create an API Key following the steps below.
- Generate a RSA 256 key pair (or using an existing key pair you already have). There are several methods of doing this.
For example, in terminal with access to openssl issue the following commands.
openssl genrsa -des3 -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem openssl rsa -in private.pem -out private_unencrypted.pem -outform PEM
- Login into the Shareworks admin portal of the environment (with the provided credentials)
- After logging in you should see the Company Choose Page with a row of buttons similar to those in the following screenshot
(the buttons you see may vary depending on how your account is configured). (Note, if you are presented with a Company Dashboard page click the link
in the upper right portion of the screen named "Choose Company" to navigate to the Choose Company page.) If you don't see the API Management button, contact Shareworks.
- Click on the API Management button. You will then see a page showing the Add API Key
button with list of any existing API keys.
- Take note of the Client ID displayed on this page as you will need it later. It is formatted with dashes for readability. You can copy it as-is or remove the dashes (as we have done in this example).
-
Click the Add API Key button and complete the form. You can give this key any arbitrary name and description but be sure to enable it. Copy your public key (full text content of public.pem file)
into the Public Signing Key field.
(Note, in the future, as needed for ongoing security, you can disable old keys and create new ones. You could even create a new RSA key pair to use as the basis of your API key).
- Click Save after you have completed the form. Then click the "Show" link to view and copy the API Secret Key.
How to Interact
cURL
The following documentation assumes that the client will be using cURL to interact with the API over HTTPS and therefore, all the examples will use cURL as their default.
Postman
Postman is another tool with a GUI that can be used to interact with the API over HTTPS. Shareworks can provide you with a JSON file of all the Shareworks Public API endpoints that you can import into Postman. You can learn more about Postman here https://www.postman.com/
Supported HTTP Response Codes
HTTP Status Code | Description |
---|---|
200 OK | Successful request. |
201 Created | Created. An object is created and returned |
400 Bad Request | The request was unacceptable, often due to missing a required parameter, malformed query, or malformed request body. |
401 Unauthorized | You request was successful and valid but you do not have access to this resource. |
403 Forbidden | The requested resource is forbidden. The server understood the request, but will not fulfill it. |
422 Unprocessable Entity | There was a validation error. Check the error message to see what values caused the error. |
500 Internal Server Error | Servers are not working as expected. |
Error Messages
Sequential Error Output
In some cases the API will encounter an error while processing a request that prevents it from doing any further processing of the request. For example, if the URL parameter "companyName" is misspelled as "comapnyName", the execution will stop at the URL error and immediately return an error response.
Aggregated Error Output
In other cases Shareworks Public API may identify several issues when performing validation checks. In such cases, the error response will list all the validation errors that were identified.
Common Errors
The most common error responses are the 400, 403, and 422. Those are explained in a little more detail below. Also note that any error response may contain an "errorId". Should you need to contact Shareworks support regarding the error please provide the errorId if one is reported.
400 Bad Request Error
This error is thrown if the URL contains illegal arguments or the body contains an invalid field type. This error is sequential error output.
400 Bad Request (Sample Response)
{
"code": "BAD REQUEST",
"message": "Could not parse the Company ID.",
"errorId": "e2671acf-395f-4091-9977-809d04086847"
}
403 Forbidden Error
This error is thrown if you try to access an entity whose identifying id is not within the purview of your access. This error is an aggregated error output. For example, trying to access a company with a companyId that is not available to you or trying to access a vestingScheduleId from an inaccessible companyId. Please note that this error will report all the Ids in the request even if only one of them is the offender.
403 Forbidden (Sample Response)
{
"code": "FORBIDDEN",
"message": "This request contains an invalid entity reference (one or more of <offendingId>, <offendinId2>).",
"errorId": "017a0276-0d59-4b39-8f10-c7b3fc613b89"
}
422 Unprocessable Entity
This error is thrown if any of the property values provided failed any type of validation during their processing. This error is an aggregated error output -- there is a separate entry in "errors" for each validation issue.422 Unprocessable Entity (Sample Response)
{
"code": "VALIDATION",
"message": "There was an issue creating a company.",
"errors": ["The company name must be unique within the system","City is required for the address"],
"errorId": "017a0276-0d59-4b39-8f10-c7b3fc613b89"
}
Date and Timezones
All HTTP response payloads should always be in UTC using the ISO-8601 formats
Data | Date and time in UTC |
---|---|
2020-12-04 | 2020-12-04T130158Z |
YYYY-MM-DD | YYYY-MM-DDThhmmss |
ISO Codes
Country Codes
Country codes use ISO-3166-2 two-letter codes e.g. "US" for United States
https://en.wikipedia.org/wiki/ISO_3166-2
State and Province Codes
For U.S. states, Shareworks Public API will accept two-letter state codes
e.g. "NY" for New York, United States
https://en.wikipedia.org/wiki/ISO_3166-2:US
Shareworks Public API will accept the province code prepended with the country code, separated by an underscore and not a hyphen
e.g. "US_NY" for New York, United States
e.g. "CA_AB" for Alberta, Canada
e.g. "AU_TAS" for Tasmania, Australia
(Example references: https://en.wikipedia.org/wiki/ISO_3166-2:CA and https://en.wikipedia.org/wiki/ISO_3166-2:AU)
Authentication
The Shareworks Public API uses Bearer authentication. In this authentication scheme a JWT (Java Web Token) is passed with each request in the HTTP Header field named "Authorization". The value of that header field should be the text "Bearer " followed by the encoded JWT. To begin interaction with the API you must first request a JWT. This is done by submitting a "verification" JWT (using the same bearer authentication scheme). Instructions for preparing a verification JWT are provided below. When submitting a valid verification JWT the response will provide new JWT. You will use the new JWT as the bearer token in subsequent requests.
Eventually, the new JWT will expire and you will need to request a new JWT (following the same process). Your API client application could proactively check the expiration of the JWT that you are using and request a new one when it is about to expire. Alternatively, your application could reactively wait for an error response that indicates the JWT is expired and then request a new one.
Create a Verification JWT
To authenticate to the Shareworks Public API you must prepare a verification JWT. The verification JWT requires:
- Your API Account's Client ID
- Your API Account's Secret Key
- Your RSA Public Key
- Your RSA Private Key
You may use https://jwt.io/ to generate the verification JWT manually. However, you will most likely want to automate this process so that your API client application can do this on demand. The format of the verification JWT is:
Header
{
"alg": "RS256",
"typ": "JWT"
}
Payload
{
"iss": "shareworks.com",
"iat": 1608767897, // use the current epoch unix time
"exp" : 1608768797, // set an expiration time
"aud" : "shareworks-api.solium.com",
"sub" : "account_number",
"grant_type" : "client_credentials",
"client_id": "WS12345678", // your client id
"client_secret": "1b347e06-8ad6-443a-8d95-411de13eb9cd", // your secret key
"jti": "52725310-2e83-4359-89b6-f6382d7bd22c" // a generated UUID
}
Verify Signature
RSASHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
-----BEGIN PUBLIC KEY-----
<public key>
-----END PUBLIC KEY-----,
-----BEGIN RSA PRIVATE KEY-----
<private key>
-----END RSA PRIVATE KEY-----
)
The code snippet below demonstrates how to construct a verification JWT in python (python 3 with the module PyJWT). This is not a fully functional script. It simply shows code related to generating a JWT. You should be able to adapt this code to other scripting or programming languages as needed.
# assume RSA key files are in current directory
PUBLIC_KEY_FILE = "public.pem"
PRIVATE_KEY_FILE = "private_unencrypted.pem"
publicKeyFile = os.path.dirname(os.path.realpath(__file__)) + os.sep + PUBLIC_KEY_FILE
if os.path.isfile(publicKeyFile):
with open(publicKeyFile) as file:
public_key = file.read()
privateKeyFile = os.path.dirname(os.path.realpath(__file__)) + os.sep + PRIVATE_KEY_FILE
if os.path.isfile(privateKeyFile):
with open(privateKeyFile) as file:
private_key = file.read()
# example uses hard-coded values, in a real script
# you would get these credentials from a file or params
PARAM_CLIENT_ID = "client_id"
PARAM_CLIENT_SECRET = "client_secret"
client_id = "WS12345678"
client_secret = "1b347e06-8ad6-443a-8d95-411de13eb9cd"
# -----------------------------------
# create encoded jwt with private key
# -----------------------------------
NOW = int(time.time())
UUID = str(uuid.uuid4())
BAD_MSG = "Are you sure your key pair is correct?"
try:
encoded = jwt.encode(
{
"iss": "shareworks.com",
"iat": NOW,
"exp": NOW + 900,
"aud": "shareworks-api.solium.com",
"sub": "account_number",
"grant_type": "client_credentials",
PARAM_CLIENT_ID: client_id,
PARAM_CLIENT_SECRET: client_secret,
"jti": UUID
},
private_key,
algorithm="RS256"
)
except:
print("Failed to encode JWT with private key. " + BAD_MSG)
exit()
# ---------------------------------------------------------
# verify jwt can be decoded with the RSA public key
# your shareworks API Key contains your public RSA key
# when you submit this encoded JWT Shareworks will attempt
# to decode it with your RSA public key
# ----------------------------------------------------------
try:
jwt.decode(encoded,
public_key,
audience="shareworks-api.solium.com",
algorithms=["RS256"])
except:
print("Failed to verify the signature with public key. " + BAD_MSG)
exit()
# ----------------
# its all good, print the jwt
# (or do something else with it --e.g. return it to some calling process)
# ----------------
print("----SUCCESS!----\n"
"Good for single use within 15 minutes\n\n"
"Copy your JWT:\n"
"----------------")
print(encoded)
Submit Verification JWT
Once you have created a verification JWT you must submit it prior to its expiration. When submitting ensure that the Content-Type Header is set to text/plain for this authentication endpoint (other endpoints expect the content type of application/json). Also note that because this is a POST with no body you will need to set the Content-Length as zero.
curl --location --request POST '<API Endpoint>/rest/admin/v1/auth/tokens'
--header 'Content-Type: text/plain' --header 'Content-Length: 0' --header "Authorization: Bearer <token>"
200 OK Response (Sample Response)
{
"accessToken": <your new token>,
"expiresIn": 5400,
"scope": "NO_ACCESS portfolio.READ_ONLY",
"issuedAt": 1608767968,
"issuer": "shareworks.com",
"audience": <your client_id>,
"tokenType": "Bearer",
"sessionId": 4938326202027
}
You have now authenticated into the Shareworks Public API and can now make calls to all the authorized endpoints using the new token.
If you don't provide a Bearer Token
401 Error Response (Sample Response)
{
"code": "UNAUTHORIZED",
"message": "The access token is missing.",
"errorId": "16248226-12ec-4244-9e48-57d8ffd069bb"
}
If you provide a malformed JWT token that cannot be processed
401 Error Response (Sample Response)
{
"code": "UNAUTHORIZED",
"message": "The access token is invalid.",
"errorId": "dd216ff1-50e2-4e96-a7d8-00155f55030d"
}
Performance and Rate Limiting
The Shareworks API is rate limited to prevent abuse that would degrade our ability to maintain consistent API performance for all users. If your requests are being rate limited, HTTP response code 429 will be returned with an rate_limit_exceeded error.
Our Limits
HTTP | Burst Threshold | Active Threshold |
---|---|---|
non-POST | 18 hits per second (during any 5 second period) | 12 hits per second (during any 2 minute period) |
POST | 5 hits per second (during any 5 second period) | 3 hits per second (during any 2 minute period) |
Endpoints
Each endpoint is designated as Read Access (available to both Read-Only and Read-Write API Clients) or Write Access (only available to Read-Write API Clients). Shareworks administrators will configure individual API accounts as having either Read-Only or Read-Write access.