Sections |
---|
Init and Authorize |
FileSystem API |
Link API |
Permissions API |
Search |
Events |
Impersonation |
Error handling |
Egnyte SDK contains methods helping the developer with authorization, FileSystem API and Link API.
For more details on the API behind this JavaScript wrapper, visit Public API documentation
Need API key? Get API access here!
Initialize Egnyte SDK to use API with your key
var egnyte = Egnyte.init("https://mydomain.egnyte.com", {
key: YOURAPIKEY,
scope: SCOPE_STRING //optional, scope value to send with token requests
mobile: true //optional, changes login prompt to mobile friendly
});
Request an access token
Call any of the API.auth.requestToken*
methods.
If the token is already stored securely and there is no need to request it, it can be passed as initial configuration.
var egnyte = Egnyte.init("https://mydomain.egnyte.com", {
token: YOURAPITOKEN
});
If you want to set some defaults for all requests (like request timeout) you can pass them to the init function:
var egnyte = Egnyte.init("https://mydomain.egnyte.com", {
requestDefaults: {
timeout: 30000
}
});
Defaults are added to the set of options passed to xhr
(in browser) or request
(in node) module.
The API has limits for the number of queries a single user can make. If one of the users of your app performs too many actions, the API endpoint will return HTTP403
with the "Developer over QPS" error.
The SDK transparently handles user quota by default. All calls have a default retry policy - if the API responds with "Developer over QPS" error, a retry is scheduled to run after 1 second. A warning is logged to the browser's console to help spotting the problem.
API.manual.promiseRequest
and all the API.storage.*
etc. methods have a built-in mechanizm to delay calls that are made too fast, to avoid getting "Developer over QPS" errors at all. The delays are based on a declared QPS value. Most API keys have a 2 queries per second limit on users.
To set your query per second quota to something else than 2, initialize with QPS
option
var egnyte = Egnyte.init("https://mydomain.egnyte.com", {
key: YOURAPIKEY,
mobile: true,
QPS: 2
});
To entirely disable the quota handling set handleQuota
option to false
Method | Arguments | Description | Restrictions |
---|---|---|---|
API.auth.isAuthorized | Returns boolean true if a token is present |
||
API.auth.setToken | token |
Accepts a token string. New token overwrites the previous one | |
API.auth.requestTokenReload | success_callback , denied_callback |
Reloads the page to perform authorization and calls the appropriate callback synchronously once the token is available or denied after reload. (see examples/request_token.html) | browser only |
API.auth.requestTokenPopup | success_callback , denied_callback ,postmessage_sender |
Opens a new window or tab for the user. postmessage_sender is a fully qualified HTTPS URL to a copy of dist/resources/token.html . (see examples/request_token_popup.html) |
browser only |
API.auth.requestTokenIframe | node , success_callback , denied_callback , path |
Performs authorization in an iframe instead of reloading the page. Iframe is appended to node . path argument is used as a redirect target for log-in prompt completion. path defaults to current window location. (see examples/request_token_iframe.html) |
browser only |
API.auth.requestTokenIframeWithPrompt | node , success_callback , denied_callback , path |
Same as above, but will prompt for Egnyte domain address first. | browser only, not available in slim.js |
API.auth.requestTokenByPassword | username , password |
Performs authorization using login and password provided by the user and resolves to the access token. Using this auth method requires switching your API key settings to be an "internal application", which is only available for Egnyte partners. (Contact us if you need that) | node.js only |
API.auth.authorizeXHR | XHR object |
Adds authorization header to given XHR object | browser only |
API.auth.getHeaders | Returns headers definition to add as headers to eg. jQuery.ajax options | ||
API.auth.getToken | Returns the token string | ||
API.auth.dropToken | Forgets the current token | ||
API.auth.getUserInfo | Returns a promise that resolves to user info object |
API.auth.requestToken
method loads the log-in prompt in current window. Once the user accepts or denies access, current page is loaded again and the whole code on it runs again. This time API.auth.requestToken
will find the token as it was appended to URL and runs the success callback.
API.auth.requestTokenReload(function(){
//can work with API
},function(){
//request denied
});
API.auth.requestTokenPopup
method opens a window or tab with the log-in prompt. Once the user accepts or denies access, postmessage_sender
is loaded in the window and the token is transmited to our main window. postmessage_sender
must be a HTTPS URL pointing to a document, that calls API.auth._postTokenUp()
, like the token.html
file in dist/resources
.
API.auth.requestTokenPopup(
function(){
//can work with API
},
function(){
//request denied
},
"https://127.0.0.1:9999/dist/resources/token.html"
);
API.auth.requestTokenIframe
method appends an iframe to given node
and opens the log-in prompt in there. Once the user accepts or denies access, current page is loaded again in the iframe and the token is extracted from it. It is recommended to pass path
to API.auth.requestTokenIframe
to redirect to an empty page, not the current one. the path
should be an absolute path in the current domain (starting with /).
API.auth.requestTokenIframe(
document.body,
function(){
//can work with API
},
function(){
//request denied
},
"/empty.html"
);
If you pass a stored token to your new Egnyte instance and the token is invalid, you should initialize again and request a new token.
To ease the handling of this situation you can pass onInvalidToken
option containing a function that will be called instead of error callback whenever your acces token turns out invalid.
var egnyte = Egnyte.init("https://mydomain.egnyte.com", {
token: YOURAPITOKEN,
key: YOURAPIKEY,
mobile: true,
onInvalidToken: function(){
//try getting new
egnyte.API.auth.requestTokenPopup(
function(){
//can work with API
},
function(){
//request denied
},
"https://127.0.0.1:9999/dist/resources/token.html"
);
//get the app working again
}
});
Method | Arguments | Description |
---|---|---|
API.manual.getEndpoint | Returns the public API endpoint root URL | |
API.manual.sendRequest | options , callback |
Sends an authorized request and calls the callback when finished (see examples below); Retries the call if server responds with "Developer over QPS"; Returns the raw XHR object in the browser and a request object in node.js |
API.manual.promiseRequest | options |
Performs the same task as sendRequest but returns a simple promise instead of calling the callback (see examples below); Automatically delays a call if it could go over QPS quota; Retries the call if server responds with "Developer over QPS" |
Request options
Name | Type | Description |
---|---|---|
url | String | The URL to query |
params | Map | Set of query params, optional |
sync | Boolean | Make a synchronous call, optional |
method | String | Request method, optional, defaults to GET |
timeout | Number | Set a timeout for the request, optional, defaults to 5s |
headers | Map | Request headers, optional |
body | String | Body of the request for POST and PUT, optional |
json | Object | JSON serializable object to send as body, adds correct content-type too, optional |
Examples
egnyte.API.manual.sendRequest({
url:"https://..." //full URL address
params:{ //query params to be added after the ? at the end of url
"queryparam":"param-value"
},
headers:{}, //any headers to add to the query, Authorization header is added to this set by default
method: "POST",
body: "some content"
}, function (error, response, body) {
if(error === null){
//response is the XHR object
//body contains response JSON converted to object
}else{
//handle the error or rethrow
}
});
egnyte.API.manual.promiseRequest({
...
}).then(function (response, body) {
//response is the XHR object
//body contains response JSON converted to object
}).fail(function(error, response, body){
//handle the error
});
egnyte.API.manual.promiseRequest({
...
}).then(function (response, body) {
//response is the XHR object
//body contains response JSON converted to object
},function(error, response, body){
//handle the error
});
Anywhere a response object is returned (except IE8/9, see Legacy support page) it is an XMLHttpRequest object extended with statusCode
field and headers
object (so you don't have to query headers individually)
All API helpers return promises.
Method | Arguments | Description | Restrictions |
---|---|---|---|
API.storage.identify(...).exists | entryID(optional) |
Resolves to true if file exists and false if it doesn't, rethrows errors if different than 404. entryID is the identifier of the version of the file if the operation should be performed on a version |
|
API.storage.identify(...).get | Resolves to file or folder definition object. | ||
API.storage.identify(...).download | entryID(optional) , isBinary |
Resolves to XHR object for the download file content query, from which response can be extracted and interpreted as needed. xhr.responseType is set to arraybuffer if isBinary is true (to get the gist of what this method can do take a look at examples/filepicker_usecase.html ). entryID is the identifier of the version of the file if the operation should be performed on a version |
browser only |
API.storage.identify(...).getFileStream | entryID(optional) |
Resolves to the response object of the API, with a paused data stream. This method also handles queueing and QPS limits transparently. | node.js only |
API.storage.identify(...).createFolder | Creates a folder at the given path, resolves to {path:"..."} or fails if folder can't be created (also if it already exists) |
||
API.storage.identify(...).storeFile | Blob or Stream , mimeType (optional) , size (optional) |
Uploads a file and stores at the given path, resolves to {path:"...",id:"<version ID>"} (see below for details on Blob). In the browser it accepts Blob, in node.js a stream should be passed as a second argument. |
size argument only works in node.js |
API.storage.identify(...).streamToChunks | Stream , mimeType (optional) , chunksize(optional) |
splits a stream in chunks and uses chunked upload to send it to Egnyte. Accepts path, stream, optional mime type and optional chunk size. Chunk size defaults to 10KB but it can be as much as 100MB if you know the file's big. Resolves to the same signature as storeFile and fails if any chunk failed to upload |
node.js only |
API.storage.identify(...).move | new path |
Moves a file or folder to new path, resolves to {path:"...", oldPath:"..."} |
|
API.storage.identify(...).copy | new path |
Copies a file or folder to new path, resolves to {path:"...", oldPath:"..."} |
|
API.storage.identify(...).rename | new path |
alias for move | |
API.storage.identify(...).remove | entryID(optional) |
Deletes a file or folder. entryID is the identifier of the version of the file if the operation should be performed on a version |
|
API.storage.identify(...).removeFileVersion | version_ID |
Deletes a version of a file, throws if version not provided (can't delete the whole file accidentally) | |
API.storage.identify(...).lock | previous token , timeout |
Locks a file, resolves to {path: "...", timeout:seconds,lock_token:"..."} , timeout defaults to 3600, previous token has to be provided if file is already locked and the lock is supposed to be renewed or overriden |
|
API.storage.identify(...).unlock | token |
Unlocks a file if the token is the one with which the lock was claimed |
Method | Argument --- | --- | --- API..path | full path to file, starting with / API..fileId | group_id of the file API.*.folderId | folder_id of the folder
var fileStream = fs.createReadStream('sample.txt')
egnyte.API.storage.path(pathFromRoot).storeFile(fileStream, "text/plain", 1105)
.then(function(filemeta){
//
})
If the API responds with an error that you cannot store an empty file, it means you have to provide the size
argument.
Storing a file requires a Blob
compatible object. It can be created manually using the browser's Blob
constructor or BlobBuilder
. A file input in a form can also produce a blob: fileInputNode.files[0]
is a File
object, which actually extends Blob
.
To aid working with blobs cross-browser we recommend https://github.com/eligrey/Blob.js (a copy available in this repo in src/vendor/blob.js)
$(".myForm").on("submit",function(){
var file = $("input.avatarfile")[0].files[0]
egnyte.API.storage.path("/Private/mydata/avatar.png").storeFile(file, "image/png")
.then(function (response, body) {
//upload successful
},function(error, response, body){
//handle the error
});
return false;
});
The storeFile
method uses FormData
constructor; documentation and detailed browser support can be found here: https://developer.mozilla.org/en-US/docs/Web/API/FormData
It is possible to download a file to memory in modern browsers. A proof of concept of that can be found in examples/filepicker_usecase.html
In node.js getFileStream resolves to a paused stream that has to be manually resumed when you're ready to accept its data.
egnyte.API.storage.path(pathFromRoot).getFileStream()
.then(function(pausedResponse){
pausedResponse.pipe(whereverYouWant);
pausedResponse.resume(); //Be sure to resume the paused stream
});
All API helpers return promises.
Method | Arguments | Description | Restrictions |
---|---|---|---|
API.storage.path(path to file ).addNote |
note_text |
Adds a note on file, resolves to {id:"note-id"} |
|
API.storage.path(path to file ).listNotes |
query_params |
Resolves to an object with pagination options and notes field containing a list. You can pass query params to set offset, limit etc. (refer to public API docs) |
|
API.storage.getNote | note_id |
Resolves to a note object. | |
API.storage.removeNote | note_id |
Removes the note. |
In current Egnyte Public API version notes can be added only to files identified by path.
All API helpers return promises.
Method | Arguments | Description |
---|---|---|
API.link.createLink | link_setup |
Creates a link, resolves to the new link description object |
API.link.removeLink | link_ID |
Destroys the link of given id |
API.link.listLink | link_ID |
Resolves to link description object |
API.link.listLinks | filters |
Resolves to a list of links, narrows the list down by filters given |
API.link.findOne | filters |
Resolves to a link description object of a link that matches the filters. (the result of listLink called on first of the ids returned by listLinks ) |
To create a link with API.link.createLink
method, a setup object is required.
Name | Description | |
---|---|---|
path | required | full absolute path to the target file or folder. If target is a file then include the filename. |
type | required | "file" or "folder" |
accessibility | required | "anyone", "password", "domain", "recipients" |
recipients | optional | list of recipients of the link (email addresses). Only required if the link will be sent via email by Egnyte. |
send_email | optional | if True, send the link out via email. In this case, the recipients parameter must be specified. Defaults to false. |
message | optional | personal message to be sent in link email. |
copy_me | optional | if True, send a copy of the link message to the link creator. Only applies if send_email is True. Defaults to false. |
notify | optional | if True send notification emails to link creator when link is accessed. Defaults to false. |
link_to_current | optional | if True, link to the current version of the file. Otherwise link to latest version of file. Only applies to file links, not folder links. Defaults to false. |
expiry_date | optional | the expiry date for the link. Date must be in the future. If expiry_date is specified then expiry_clicks cannot be set. |
expiry_clicks | optional | the number of clicks the link is valid for. Value must be between 1 and 10, inclusive. If expiry_clicks is specified then expiry_date cannot be set. |
add_file | optional | if True then the filename will be appended to the end of the link. Only applies to file links, not folder links. Defaults to false. |
accessibility options:
- "anyone" – accessible by anyone with link
- "password" – accessible by anyone with link who knows password (password is generated and returned from the call)
- "domain" – accessible by any domain user (login required)
- "recipients" – accessible by link recipients, who must be domain users (login required)
Example
egnyte.API.link.createLink({
path: "<file path>",
type: "file",
accessibility: "password"
}).then(function (newLink) {
newLink.links[0].id; //link ID, useful when listing or removing link
newLink.links[0].url; //the URL of your link
newLink.password; //autogenerated password to enter the link
});
Full link description example
{
"links": [{
"id": "yshJEeonvt",
"url": "https://acme.egnyte.com/h-s/20140528/yshJEeonvt",
"recipients": []
}],
"path": "/Private/acme/filename.png",
"type": "file",
"accessibility": "password",
"notify": false,
"password": "xi3awtc3ZphJ",
"link_to_current": false,
"creation_date": "2014-05-28",
"send_mail": false,
"copy_me": false
}
API.link.listLinks
and API.link.findOne
methods accept filters definition. All filters are optional.
Name | Description |
---|---|
path | list links to this file or folder (full absolute path) |
username | list links created by this user |
created_before | list links created before this date |
created_after | list links created after this date |
type | show links of this type (“file” or “folder”) |
accessibility | show links with this accessibility (“anyone”, “password”, “domain” or “recipients”) |
offset | start at this link (0 = first link). If not specified, defaults to 0. |
count | send this number of links. If not specified, all links will be sent. |
Example response to listLinks
{
"total_count": 10,
"offset": 5,
"count": 3,
"ids": ["47b774f66f344a67","56d35b2320d74948","426683f37dd64e41"]
}
All API helpers return promises.
All the methods below can be scoped to users or groups.
Method | Arguments | Description |
---|---|---|
API.perms.users | users[] |
Returns API.perms instance scoped to a certain set of users. |
API.perms.groups | groups[] |
Returns API.perms instance scoped to a certain set of groups. |
API.perms.identify(...).allow | accessLevel |
Sets certain permissions on the given folder for the users/groups it's scoped to. Second argument is one of "None", "Viewer", "Editor", "Full", "Owner" |
API.perms.identify(...).disallow | Sets permissions on the given folder to "None" for the users/groups it's scoped to. | |
API.perms.identify(...).allowView | Sets permissions on the given folder to "Viewer" for the users/groups it's scoped to. | |
API.perms.identify(...).allowEdit | Sets permissions on the given folder to "Editor" for the users/groups it's scoped to. | |
API.perms.identify(...).allowFullAccess | Sets permissions on the given folder to "Full" for the users/groups it's scoped to. | |
API.perms.identify(...).allowOwnership | Sets permissions on the given folder to "Owner" for the users/groups it's scoped to. | |
API.perms.identify(...).getPerms | Resolves to a permissions object of the folder. If scoped to users/groups, only permissions relevant to them will be returned. |
Method | Argument --- | --- | --- API..path | full path to file, starting with / API..folderId | folder_id of the folder
Scoping to users and groups can be merged
egnyte.API.perms.users(["tommy","margaret"]).groups(["All Power Users"]).path("/Shared/marketing/events").allowEdit()
Scoping again will override the previous setting, so the example below will only set permissions for "andy".
egnyte.API.perms.users(["tommy","margaret"]).users(["andy"]).path("/Shared/marketing/events").allowEdit()
All permissions for folder:
egnyte.API.perms.path("/Shared/marketing/events").getPerms()
Returns
{
"users": [{
"subject": "admin",
"permission": "Owner"
}, {
"subject": "tommy",
"permission": "Editor"
}, {
"subject": "margaret",
"permission": "Editor"
}],
"groups": [{
"subject": "All Power Users",
"permission": "Editor"
}]
}
Filtered permissions information:
egnyte.API.perms.users(["tommy"]).path("/Shared/marketing/events").getPerms()
Returns
{
"users": [{
"subject": "tommy",
"permission": "Editor"
}],
"groups": []
}
All API helpers return promises.
Method | Arguments | Description |
---|---|---|
API.userPerms.identify(...).get | username |
Resolves to effective permissions for given user. username defaults to the user making the request. |
Method | Argument --- | --- | --- API..path | full path to folder, starting with / API..folderId | folder_id of the folder
egnyte.API.userPerms.path("/Shared/Documents").get()
Returns
{
"permission": "Full"
}
All API helpers return promises.
Method | Arguments | Description |
---|---|---|
API.user.getByName | user name |
Resolves to complete user metadata object |
API.user.getById | user id |
Resolves to complete user metadata object |
Method | Arguments | Description |
---|---|---|
API.search.getResults | query text |
Resolves to a helper object for fetching search results |
API.search.query | query text , page number |
Low level search query function, resolves to a single body of the search response. Is used internally in getResults |
API.search.itemsPerPage | number |
Updates the number of items per page for search. default: 10 |
Results object:
Name | Description |
---|---|
totalCount | Number of all results |
totalPages | Number of available pages with results |
sample | First page of results (array of search results you'd get from calling .page(0) |
page(num ) |
method to get a certain page of results; resolves to an array of results |
Pages are numbered starting at 0.
Method | Arguments | Description |
---|---|---|
API.events.listen | listenerConfiguration |
Polls the Events API for new events and emits them according to configuration. Resolves to an object with a single stop method that stops getting more events. |
API.events.getCursor | Resolves to the latest event id | |
API.events.getUpdate | updateOptions |
Makes a single request for a list of events and resolves to the response. getUpdate is used internally by listen . |
listenerConfiguration:
Name | Description | |
---|---|---|
start | event id - get events that happened after that id. Fails if event is too old (.listen promise gets rejected). If not set, it will get only the events that happen since the moment of invocation. | |
interval | miliseconds between making requests for events. minimum possible value is 2000, defaults to 30000 | |
emit | required | a function to call when an event is received. the function accepts one argument - event data object. |
error | function to call when fetching events fails | |
current | function to call with the latest event id discovered | |
heartbeat | a debug callback to be called whenever a request to events API is made. |
updateOptions:
Name | Description | |
---|---|---|
start | required | event id - get events that happened after that id. Fails if event is too old (promise gets rejected). |
emit | a function to call for every event in the batch. the function accepts one argument - event data object. Optional, you can decide to use the raw output | |
count | number of events to fetch. Maximum value is 100 |
Method | Arguments | Description |
---|---|---|
API.events.notMy | "user" (optional) |
Sets up filtering to ignore events caused by the same app that is querying events. If "user" is passed as first argument, only events caused by current user of the app are ignored. Returns API.events , so it's chainable |
API.events.filter | filterDefinition |
Sets up filtering to only return events matching the definition. Can filter by folder path or event type or both. Returns API.events , so it's chainable |
filterDefinition:
{
folder: "/folder/path",
type: "file_system" or "note"
}
Example:
egnyte.API.events.notMy().filter({
folder: "/Shared/marketing/events"
}).listen({
emit: function(eventData){
//process event
},
interval: 10000,
heartbeat: function(){
console.log(".");
}
}).then(function(polling){
//call polling.stop() to turn the listener off
})
All errors are returned in common format of a JavaScript error enhanced with additional fields
Name | Description |
---|---|
statusCode | HTTP status code if error comes from the server. 0 if request failed before being sent. undefined if error occured in the source of this SDK |
message | readable error message text |
response | If the query happened, error.response is the xhr response object |
body | If the query happened, error.body contains the body of the response |
The "Developer over QPS" error is not returned at all, instead a call is repeated when appropriate.
Egnyte Public API accepts a X-Egnyte-Act-As
header that can be set to perform an action on behalf of another user (if you are an admin).
Every method call to egnyte.API.*
can be preceded by impersonation like so:
egnyte.API.link.impersonate({username:"username"}).createLink(...
egnyte.API.link.impersonate({email:"[email protected]"}).createLink(...
You can store an impersonated facade to use multiple times or pass it along to other components that don't need to have access to username, but need to perform on behalf of that user.
var impersonatedStorage = egnyte.API.storage.impersonate({username:"username"});
impersonatedStorage.path("/path...").exists();
You can provide a request function as the httpRequest
option.
It has to accept an options
object and a result callback function(error, responseObject, responseBody)
It should be compatible with npm module called xhr.