MyWhistleBox provides developers a path to integrate their applications to the MyWhistleBox service through an Application Programming Interface (API). This is a great way to extend the MyWhistleBox service using an existing workflow.
Here are a just a few examples of things you can do with the REST API:
The MyWhistleBox API is implemented using a REST model and requires an Enterprise plan. The REST model uses standard HTTP requests to communicate with the
MyWhistleBox API service. Developers can use any programming language that support standard HTTP request calls.
A public PHP wrapper is available on github located at
.
Although the wrapper makes things a bit easier to implement using PHP, any HTTP library like cURL can be used to make requests and handle return values.
To access a REST endpoint via the service, construct a URL using the base endpoint along with an action suffix described below.
The base endpoint for the REST service is
MyWhistleBox uses a simple API Key for authentication. All requests must contain a valid API key. You simply make an HTTP Request
by including the following header:
The "apikey" can be generated and copied from your MyWhistleBox Account Settings API Tab (see Configuration Guide).
The endpoints (actions) below are described using the following form:
Content-Type: application/x-www-form-urlencoded is assumed unless noted.
For example, a generic request would look like:
https://mywhistlebox.com/api/rest/v1.0/{action}/<params>
e.g. To list the boxes in your account (no params required).
Send a http request with the GET method type along with the Authorization header and url:
The action's response (if any) will be decribed in the Response portion.
To make integrating easier, we offer a php api sdk library. Instructions are included with the sdk. You can also use any request
mechanism your language offers including cURL. If you want to use cURL, check out the cURL example document on the developer home page.
To get familiar with using the endpoints, we provide a test endpoint called /test/ping. You can use this endpoint to
determine if your authentication process is working and your request is reaching the REST server.
If the response is “ok”, your request has reached the service and your APIKey has been authorized.
Some endpoints require Date or Date/Time inputs. These values should be formatted following the ISO 8601 format. An example of a date parameter is:
In addition to the Responses noted for each endpoint, all endpoints can receive an error Response in the following form:
If you receive an Access Denied error, this typically mean the APIKey can't be validated (due to typos or revocation),
or the account lacks API access. If you are sure your request is formatted properly, check to make sure you copied and pasted the API key correctly.
Keys shouldn't contain any spaces.
External processes can register a webhook to fire when certain events occur within MyWhistleBox. This eliminates the need for polling.
A webhook registration is comprised of an event type, a url and an optional filter.
When the event occurs, MyWhistleBox will "call back" the provided url with event information.
This information can be used by the external process to perform some action.
Filters are an optional json structure included with the request used to limit event firings to certain conditions.
The same thing can be achieved on the receiving end by inspecting the fired event properties.
Filters should be in the following structure:
When the webhook url is called, it will include the following event properties.
Actions are grouped into categories. To query certain resources, it may be necessary to query more than one endpoint.
For example, /file/info requires a "file_id". You could first use the /list/files endpoint to obtain the desired file_id and then use that id with the
/file/info endpoint.
A list of endpoints by
Use these category tabs to obtain more details of each endpoint.
GET /list/boxes
Summary: List all boxes for this account.
Request Body {
}
Responses
200 OK: {
status: "ok",
boxes: [{
id: box id,
name: box name
}],
defaultBoxId: default box id
}
GET /list/pages
Summary: List all WhistlePages for this account.
Request Body {
}
Responses
200 OK: {
status: "ok",
pages: [{
id: whistlepage id,
name: whistlepage name
}]
}
GET /list/folders/<parent_id>
Summary: List all first level child folders in specified box or folder.
Request Body {
<parent_id>: id of the parent folder [required]
}
Responses
200 OK: {
status: "ok",
folders: [{
id: folder id,
name: folder name
}]
}
GET /list/files/<folder_id>
Summary: List all files in specified box or folder.
Request Body {
<folder_id>: id of the folder files reside in [required]
}
Responses
200 OK: {
status: "ok",
files: [{
id: file id,
name: file name
}]
}
GET /list/memos/<folder_id>
Summary: List all memos (personal notes) in specified memo folder.
Request Body {
<folder_id>: id of the memo folder [required]
}
Responses
200 OK: {
status: "ok",
memos: [{
id: memo id,
title: memo title
}]
}
GET /list/templates
Summary: List all Signature Templates for this account.
Request Body {
}
Responses
200 OK: {
status: "ok",
files: [{
id: template file id,
name: template file name
}]
}
POST /user/file/upload
Summary: Upload file contents to a users box.
Content-Type: multipart/form-data
Request Body {
address: WhistleBox address string of user, [required]
file: form-data formatted file contents, [required]
confirmEmail: email for confirmation,
subject: subject of the file,
note: note attached to the uploaded file,
}
Responses
200 OK: {
status: "ok",
id: id of the new uploaded file
}
POST /user/file/uploadUrl
Summary: Upload a file to a users box using the file url.
Request Body {
address: WhistleBox address string of user, [required]
fileUrl: file path string to the remote file to be uploaded, [required]
fileName: optional file name to override the fileUrl name,
confirmEmail: email for confirmation,
subject: subject of the file,
note: note attached to the uploaded file,
}
Responses
200 OK: {
status: "ok",
id: id of the new uploaded file
}
POST /user/memo/upload
Summary: upload a personal note to a users box
Request Body {
address: WhistleBox address string of user, [required]
title: title of the memo, [required]
text: memo text [required]
}
Responses
200 OK: {
status: "ok",
id: id of the new memo
}
POST /user/file/send/<file_id>
Summary: send an account file to a users box
Request Body {
<file_id>: optional id of the file to be sent,
file_ids: comma separated list of file_ids, [required?]
address: WhistleBox address of user, [required]
confirmEmail: email for confirmation,
note: note attached to the uploaded file
}
Responses
200 OK: {
status: "ok",
fileCount: number of files sent,
to: recipient address,
sentStatus: [{
id: file id,
file: file name,
result: result of send
}]
}
POST /user/file/sendsign/<file_id>
Summary: send an account file to a users box for signature
Request Body {
<file_id>: id of the file to be sent [required]
address: WhistleBox address of user, [required]
template_id: id of a signature template
note: note attached to the uploaded file
}
Responses
200 OK: {
status: "ok",
to: recipient address,
sentStatus: {
id: file id,
file: file name,
result: result of send
}
}
Note: If <file_id> is omitted, file_ids are required
POST /folder/upload/<folder_id>
Summary: direct upload a file contents to our folder
Content-Type: multipart/form-data
Request Body {
<folder_id>: our target folder id [required]
file: form-data formatted file to the local file to be uploaded [required]
}
Responses
200 OK: {
status: "ok",
id: id of the new file
}
POST /folder/uploadUrl/<folder_id>
Summary: direct upload a file via URL to our folder
Request Body {
<folder_id>: our target folder id [required]
fileUrl: file path string to the remote file to be uploaded [required]
fileName: optional file name to override the fileUrl name,
}
Responses
200 OK: {
status: "ok",
id: id of the new file
}
POST /folder/<parent_id>
Summary: Create a new folder in parent
Request Body {
<parent_id>: id of the parent folder we want to create in [required]
name: name of folder to be created [required]
}
Responses
200 OK: {
status: "ok",
id: id of the new folder
}
GET /file/info/<file_id>
Summary: get a file's metadata
Request Body {
<file_id>: id of target file [required]
}
Responses
200 OK: {
status: "ok",
file: {
id: file id,
name: file name,
size: size in bytes,
mimeType: file mime type,
senderName: name of person who uploaded,
company: sender company,
subject: subject of file,
notes: file note,
confirmed: has this file been confirmed received?,
unread: has this file been unread?,
signed: is this file signed?,
created: created date (gmt),
modified: modified date (gmt)
}
}
GET /file/download/<file_id>
Summary: download a file
Request Body {
<file_id>: id of target file [required]
}
Response: Full file contents. File name and mime type included in http response header. Typically response content should be
saved to a local file with the name specified in the header.
POST /file/search
Summary: search account for files
Request Body {
srchName: file name (default ''),
srchSubject: file subject (default ''),
srchSender: file sender (default ''),
srchDateFrom: file Date From (default ''),
srchDateTo: file Date To (default ''. If not '', file date is range DateFrom to DateTo),
srchUnread: Search Unread files (0 or 1 default 0),
srchSigned: Search for Signed Files (0 or 1 default 0),
srchTrash: Search Trash (0 or 1 default 0),
srchWhistlePage: Search for Include WhistlePage (0 or 1 default 0),
srchTemplates: Search for Signature Template (0 or 1 default 0)
}
Responses
200 OK: {
status: "ok",
file: [{
id: file id,
folderId: folder id,
boxId: box id,
path: file path (from box),
name: file name,
size: size in bytes,
mimeType: file mime type,
senderName: name of person who uploaded,
company: sender company,
subject: subject of file,
notes: file note,
confirmed: has this file been confirmed received?,
unread: has this file been unread?,
signed: is this file signed?,
signatureTemplate: is this a signature template?,
pageLinked: is available in WhistlePages?,
created: created date (gmt),
}]
}
GET /memo/<memo_id>
Summary: fetch a memo
Request Body {
<memo_id>: id of memo [required]
}
Responses
200 OK: {
status: "ok",
memo: {
id: memo id,
title: memo title,
text: memo contents,
created: created date (gmt),
modified: modified date (gmt)
}
}
POST /memo/<folder_id>
Summary: create a new memo
Request Body {
<folder_id>: memo folder id [required],
title: memo title string [required],
text: memo text string [required]
}
Responses
200 OK: {
status: "ok",
id: memo id
}
POST /request/upload/<box_id>
Summary: email an upload request
Request Body {
<box_id>: id of the upload target box [required]
email: email address of recipient [required]
expireDays: how many days before email link expires (0-14)
note: note to be included with email body
}
Responses
200 OK: {
status: "ok"
}
POST /request/whistlepage/<page_id>
Summary: email a whistlePage request
Request Body {
<page_id>: id of the page to be requested [required]
email: email address of recipient [required]
expireDays: how many days before email link expires (0-14)
note: note to be included with email body
}
Responses
200 OK: {
status: "ok"
}
POST /request/signature/<file_id>
Summary: email a signature request
Request Body {
<file_id>: optional id of the file to be signed
file_ids: comma separated list of file_ids [required?]
email: email address of recipient [required]
accessType: Security type required of signor [required]
accessCode: security code signor must enter [required?]
expireDays: how many days before email link expires (1-14)
template_id: id of a template file used to apply to the signature document
note: note to be included with email body
}
Responses
200 OK: {
status: "ok"
}
Notes:
- If <file_id> is omitted, file_ids are required
- accessType: 'NONE', 'SSN4', 'SSN5', 'ZIP5', 'PHONE4', 'CUSTOM'
- accessCode is required if accessType is not NONE.
POST /request/download/<file_id>
Summary: email a download request
Request Body {
<file_id>: optional id of the file to be signed,
file_ids: comma separated list of file_ids [required?],
email: email address of recipient [required],
accessType: Security type required of signor [required],
accessCode: security code signor must enter [required?],
expireDays: how many days before email link expires (1-14),
note: note to be included with email body
}
Responses
200 OK: {
status: "ok"
}
Notes:
- If <file_id> is omitted, file_ids are required
- accessType: 'NONE', 'SSN4', 'SSN5', 'ZIP5', 'PHONE4', 'CUSTOM'
- accessCode is required if accessType is not NONE.
POST /report/log/upload
Summary: generate upload request log report. For large reports, can be called repeatedly to get record sets.
Request Body {
startDate: report period start (YYYY-MM-DD) [required],
endDate: report period end (YYYY-MM-DD) [required],
limit: max records to return (default 5000),
startAt: start record number(default 0)
}
Responses
200 OK: {
status: "ok",
entries: [{
folderId: box id,
folderName: box name,
email: recipient's email,
status: request status,
expires: expiration date,
created: created date
}],
count: number of records returned in this set,
total: total records in report,
next: record number beginning of next set (-1 if last set)
}
Notes: If total records is greater than the limit, startAt can be used in successive calls by using returned "next" value to retrieve the next set of records.
POST /report/log/whistlepage
Summary: generate WhistlePage request log report. For large reports, can be called repeatedly to get record sets.
Request Body {
startDate: report period start (YYYY-MM-DD) [required]
endDate: report period end (YYYY-MM-DD) [required]
limit: max records to return (default 5000)
startAt: start record number(default 0)
}
Responses
200 OK: {
status: "ok",
entries: [{
pageId: whistlepage id,
pageName: whistlepage name,
email: recipient's email,
status: request status,
expires: expiration date,
created: created date
}],
count: number of records returned in this set,
total: total records in report,
next: record number beginning of next set (-1 if last set)
}
Notes: If total records is greater than the limit, startAt can be used in successive calls by using returned "next" value to retrieve the next set of records.
POST /report/log/download
Summary: generate download request log report. For large reports, can be called repeatedly to get record sets.
Request Body {
startDate: report period start (YYYY-MM-DD) [required]
endDate: report period end (YYYY-MM-DD) [required]
limit: max records to return (default 5000)
startAt: start record number(default 0)
}
Responses
200 OK: {
status: "ok",
entries: [{
fileId: file id,
fileName: filename,
accessType: security access type,
accessCode: security access code,
email: recipient's email,
status: request status,
expires: expiration date,
created: created date
}],
count: number of records returned in this set,
total: total records in report,
next: record number beginning of next set (-1 if last set)
}
Notes: If total records is greater than the limit, startAt can be used in successive calls by using returned "next" value to retrieve the next set of records.
POST /report/log/signature
Summary: generate signature request log report. For large reports, can be called repeatedly to get record sets.
Request Body {
startDate: report period start (YYYY-MM-DD) [required]
endDate: report period end (YYYY-MM-DD) [required]
limit: max records to return (default 5000)
startAt: start record number(default 0)
}
Responses
200 OK: {
status: "ok",
entries: [{
fileId: file id,
fileName: filename,
accessType: security access type,
accessCode: security access code,
email: recipient's email,
status: request status,
expires: expiration date,
created: created date
}],
count: number of records returned in this set,
total: total records in report,
next: record number beginning of next set (-1 if last set)
}
Notes: If total records is greater than the limit, startAt can be used in successive calls by using returned "next" value to retrieve the next set of records.
POST /report/log/sender
Summary: generate sender log report. For large reports, can be called repeatedly to get record sets.
Request Body {
startDate: report period start (YYYY-MM-DD) [required]
endDate: report period end (YYYY-MM-DD) [required]
limit: max records to return (default 5000)
startAt: start record number(default 0)
}
Responses
200 OK: {
status: "ok",
entries: [{
wbAddress: whistlebox address,
fileId: file id,
fileName: file name,
folderName: box name,
signRequest: is a signature requested?,
expires: signing request expiration date,
downloaded: has signed document been accessed?,
confirmRequest: is a confirmation requested?,
Confirmed: has this file been confirmed?,
created: sent date
}],
count: number of records returned in this set,
total: total records in report,
next: record number beginning of next set (-1 if last set)
}
Notes: If total records is greater than the limit, startAt can be used in successive calls by using returned "next" value to retrieve the next set of records.
POST /report/log/audit
Summary: generate audit log report. For large reports, can be called repeatedly to get record sets.
Request Body {
startDate: report period start (YYYY-MM-DD) [required]
endDate: report period end (YYYY-MM-DD) [required]
limit: max records to return (default 5000)
startAt: start record number(default 0)
}
Responses
200 OK: {
status: "ok",
entries: [{
userName: name of user ,
action: what was done,
on: object of the action,
to: result of the action,
created: action date
}],
count: number of records returned in this set,
total: total records in report,
next: record number beginning of next set (-1 if last set)
}
Notes: If total records is greater than the limit, startAt can be used in successive calls by using returned "next" value to retrieve the next set of records.
GET /test/ping
Summary: test your APIKEY connection
Request Body {
}
Responses
200 OK: {
status: "ok"
}
POST /webhook
Summary: Register a webhook.
Request Body {
event: Event to be triggered (see webhook section) [required],
url: URL to be called on the event [required],
filters: An optional filter (see webhook section),
}
Responses
200 OK: {
status: "ok"
id: id of the registered webhook
}
DELETE /webhook/<id>
Summary: Destroy a webhook registration.
Request Body {
}
Responses
200 OK: {
status: "ok"
}