|
| 1 | +# Agiloft REST API — authoritative spec (transcribed from live help.agiloft.com) |
| 2 | + |
| 3 | +## GLOBAL / API Security |
| 4 | +- Every REST call should contain credentials as `login={login}&password={password}`. |
| 5 | +- POST-body credentials supported ONLY for: /ewws/EWRead, /ewws/EWSelect, /ewws/EWCreate, |
| 6 | + /ewws/EWUpdate, /ewws/EWDelete. ("avoid passing the login or password ... by using POST |
| 7 | + instead of GET to pass the parameters in the request body") |
| 8 | +- JWT: EWLogin returns a token; "The token can then be used in an Authorization request header, |
| 9 | + prefixed by the authentication scheme, instead of including the login and password parameters |
| 10 | + in following requests." Default scheme Bearer, expiry 15 min (token_expires_in, max 60). |
| 11 | +- Statefulness: pattern is "login, do multiple calls, logout". EWLogout terminates the session |
| 12 | + associated with the token passed in the Authorization header. |
| 13 | +- DELAYS: every REST call has a delay after completion, default 1 second, global var WSDelay. |
| 14 | +- Group must be REST-enabled (Setup > System > Manage Web Services > Groups allowed for REST), |
| 15 | + else 403. |
| 16 | + |
| 17 | +### General error codes (selected) |
| 18 | +- 400 "There is no permissions to access this resource" |
| 19 | +- 400 "One has to specify $login and $password parameters or authentication token." <-- BOTH auth methods provided |
| 20 | +- 400 "Token is expired" |
| 21 | +- 400 "One has to specify $login, $password parameters or use $genhotlink/$genproject pair ..." <-- no auth |
| 22 | +- 401 "Wrong Authorization data" <-- invalid authorization scheme |
| 23 | +- 401 "Token is blocked" / "User is blocked" |
| 24 | +- 403 invalid login attempt / "Authentication failed." / "Invalid login/password combination ..." |
| 25 | +- 500 "No active session found for current token" |
| 26 | +- 400 "Unable to identify KB with name" / "Cannot find specified knowledgebase: <KBName>" |
| 27 | +- 400 "One has to specify $table, $KB, $lang parameters or use $genhotlink/$genproject pair ..." |
| 28 | +- 400 "Wrong combination of access token and KB name. No access to data in KB" |
| 29 | +- 400 "One has to specify id value." |
| 30 | +- 400 "Project <projectId> has not been found" / "Table <tableId> has not been found" |
| 31 | +- 400 "No value for 'field' parameter specified." |
| 32 | +- 403 "not allowed, please check logs" (IP blacklist) |
| 33 | +- 405 "HTTP method <methodName> is not supported by this URL" |
| 34 | + |
| 35 | +## URL CONVENTIONS |
| 36 | +- KB names and table names are CASE SENSITIVE (use Logical Table Name). |
| 37 | +- REST style: `/ewws/REST/{kbName}/{table}[/{id}]?$login={login}&password={password}&lang={lang}&...` |
| 38 | + (omit /{id} for Create) |
| 39 | +- GET/POST style: `/ewws/{operation}?$KB={kbName}&$table={table}&$login={login}&password={password}&lang={lang}&...` |
| 40 | + "The parameters of the POST request can be inserted into the body of the request to conceal the user credentials." |
| 41 | +- Return values: JavaScript eval() form, all names prefixed `EWREST_`. Empty fields returned as nulls. |
| 42 | +- JSON decorator: append `/.json` -> `{"success":true,"message":"","result":{...}}` |
| 43 | + optional `err_code_resp=1` for real status codes instead of always 200. |
| 44 | +- Async decorator: `/ewws/async/EWCreate?...` or `/ewws/EWCreate/.async?...` (EWCreate, EWUpdate, EWDelete) |
| 45 | +- Redirect decorator: `/ewws/redirect/...` with $exiturl and $errorurl |
| 46 | +- Decorators chain left to right. |
| 47 | + |
| 48 | +## OPERATIONS TABLE (endpoint / methods / returns) |
| 49 | +| Create | GET/POST | /ewws/EWCreate | ID of new record | |
| 50 | +| Read | GET/POST | /ewws/EWRead | encoded record info | |
| 51 | +| Update | GET/POST | /ewws/EWUpdate | encoded record info after update | |
| 52 | +| Delete | GET/POST/DELETE | /ewws/EWDelete | nothing | |
| 53 | +| Select | GET/POST | /ewws/EWSelect | list of record ids + length | |
| 54 | +| Login | GET/POST | /ewws/EWLogin | session token, expiration, auth scheme | |
| 55 | +| Logout | GET/POST | /ewws/EWLogout | nothing | |
| 56 | +| Search | GET/POST | /ewws/EWSearch | saved search + ad hoc | |
| 57 | +| Attach | PUT | /ewws/EWAttach | total files attached | |
| 58 | +| RemoveAttached | GET/POST | /ewws/EWRemoveAttachment | nothing | |
| 59 | +| RetrieveAttached | GET/POST | /ewws/EWRetrieve | attachment | |
| 60 | +| Lock | GET/PUT/DELETE | /ewws/EWLock | lock status | |
| 61 | +| AttachInfo | GET/POST | /ewws/EWAttachInfo | attachment info | |
| 62 | +| Hotlink | POST | /ewws/EWHotlinks | hotlink | |
| 63 | +| Table | GET/POST | /ewws/EWTable | all tables and fields | |
| 64 | +| Async Status | GET/POST | /ewws/EWAsyncStatus | execution status | |
| 65 | +| GetChoiceLineId | GET | /ewws/GetChoiceLineID | internal id for a choice value | |
| 66 | +| Action Button | POST | /ewws/EWActionButton | runs an action button | |
| 67 | +| Saved Search | GET/POST | /ewws/EWSavedSearch | saved search details | |
| 68 | + |
| 69 | +NOTE: the operations table lists `/ewws/GetChoiceLineID` and `/ewws/EWActionButton`, but the |
| 70 | +detail pages use `/ewws/EWGetChoiceLineId` and `/ewws/async/EWActionButton`. Detail pages carry |
| 71 | +working curl examples; the table does not. |
| 72 | + |
| 73 | +## EWLogin |
| 74 | +POST /ewws/EWLogin, Content-Type: plain/text. |
| 75 | +Params (CAN BE FILLED TO REQUEST BODY): $KB, $login, $password, $lang (default en). |
| 76 | +Response JSON: access_token, refresh_token, expiration_time_unit, expires_in, authentication_scheme |
| 77 | + (default "Bearer " — NOTE TRAILING SPACE in examples). |
| 78 | +Example: POST https://server/ewws/EWLogin?$login=user&$password=passwd&$KB=Demo&$lang=en |
| 79 | +Refresh: POST /ewws/EWLogin with Authorization header + body refresh_token=... |
| 80 | +Logout: POST or GET /ewws/EWLogout with Authorization header; params $KB, $lang. |
| 81 | +Errors: 400 no refresh_token / wrong refresh_token; 401 Refresh Token is expired; |
| 82 | + 403 "User <userName> lacks permission log in" |
| 83 | + |
| 84 | +## EWCreate |
| 85 | +GET/POST /ewws/EWCreate. Content-Type application/x-www-form-urlencoded. |
| 86 | +Params in URL/body: $KB, $table, $login, $password, $lang + field values. |
| 87 | +Returns: EWREST_id='353'; |
| 88 | +Async-compatible. |
| 89 | +Errors: 400 "Wrong format/value pointed to <columnName>"; linked-field errors. |
| 90 | + |
| 91 | +## EWRead |
| 92 | +GET/POST /ewws/EWRead. Params: $KB,$table,$login,$password,$lang,id |
| 93 | +Alternative to id: $searchSQL=ext_id='a0B2c345' (must match exactly one record). |
| 94 | +Returns EWREST_<field>='<value>'; lines including EWREST_id. |
| 95 | +Errors: 400 "no data found for id range(s)" |
| 96 | + |
| 97 | +## EWUpdate |
| 98 | +GET/POST /ewws/EWUpdate. Params: ... id=358 + field values. |
| 99 | +Alternative to id: $searchSQL. |
| 100 | +$operationHints=NOLOCK forces update on a locked record (URL or POST body). |
| 101 | +Returns full updated record as EWREST_ lines. |
| 102 | +Errors: 400 "One has to specify id or searchSQL value."; constraint violations. |
| 103 | + |
| 104 | +## EWDelete |
| 105 | +GET/POST/DELETE /ewws/EWDelete. Params: ... id=358 & deleteRule=... |
| 106 | +deleteRule values: ERROR_IF_DEPENDANTS, APPLY_DELETE_WHERE_POSSIBLE, |
| 107 | + DELETE_WHERE_POSSIBLE_OTHERWISE_UNLINK, APPLY_UNLINK, |
| 108 | + UNLINK_WHERE_POSSIBLE_OTHERWISE_DELETE, REPLACE_WITH_ANOTHER (needs `subs`). |
| 109 | +Returns nothing on success; error message on failure. |
| 110 | +Errors: 400 "One has to specify deleteRule, id and substitute values."; |
| 111 | + 409 "Operation cannot be done. Record has <n> dependants" etc. |
| 112 | + |
| 113 | +## EWSelect |
| 114 | +GET/POST /ewws/EWSelect. Params: ... where=<sql where clause> |
| 115 | +Queries in the URL must use %N equivalent operators. |
| 116 | +SQL uses dbname column names. Choice values via GetChoiceLineId. |
| 117 | +Limit via DB syntax e.g. "limit 0,200". No sort control (use EWSearch). |
| 118 | +Returns: EWREST_id_length = '3'; EWREST_id_0 = '150'; ... |
| 119 | +Empty: EWREST_id_length = '0'; |
| 120 | +Errors: 400 "Error <error> parsing the query <query>"; 500 "Error executing query, please consult logs" |
| 121 | + |
| 122 | +## EWSearch |
| 123 | +GET/POST /ewws/EWSearch. Content-Type x-www-form-urlencoded. |
| 124 | +Params: $KB,$table,$login,$password,$lang, search=<saved search label>, query=<ad hoc>, |
| 125 | + field=<repeated>, page, limit |
| 126 | +Operators: = %3D | != %21%3D | ~= %7E%3D (contains) | && %26%26 | || %7C%7C | < <= > >= |
| 127 | +Surround each search value in single quotes; if a field label contains spaces, quote the label too. |
| 128 | +Empty fields designated with null. |
| 129 | +Returns: EWREST_length = '4'; then EWREST_<field>_<i>='value'; |
| 130 | +Empty: EWREST_id_length = '0'; |
| 131 | +Pagination: page starts 0. limit 0 = ALL records on page 0. |
| 132 | + "The REST interface creates a new session and performs an explicit logout for each call. |
| 133 | + As such, though pagination is available, the query will always be rebuilt and rerun." |
| 134 | +ALREST EQUIVALENT (documented in this page): |
| 135 | + curl --location 'http://localhost:8080/ewws/alrest/CLM Template/case/search?lang=en' \ |
| 136 | + --data '{ "field": ["id","summary"], "query": "summary=test" }' |
| 137 | +Errors: 400 "No search <savedSearch> for table <tableName>"; 400 "No column <columnName> in table <tableName>" |
| 138 | + |
| 139 | +## EWAttach |
| 140 | +PUT /ewws/EWAttach. Content-Type multipart/form-data (file in body). |
| 141 | +Params: $KB,$table,$login,$password,id,field,fileName |
| 142 | +Returns: EWREST_someField.length='1'; (key is `<fieldName>.length`) |
| 143 | +Errors: 400 "No value for 'fileName' parameter specified."; forbidden extension etc. |
| 144 | + |
| 145 | +## EWAttachInfo |
| 146 | +GET/POST /ewws/EWAttachInfo. Example uses /.json |
| 147 | +URL: /ewws/EWAttachInfo/.json?$KB=..&$table=..&$lang=en&field=attached_file&$login=..&$password=..&id=1 |
| 148 | +Returns: {"success":true,"message":"","result":[{"fileName":"..","size":22126,"filePosition":0}]} |
| 149 | + |
| 150 | +## EWRemoveAttachment |
| 151 | +GET/POST /ewws/EWRemoveAttachment. Params: $KB,$table,$login,$password,id,field,filePosition |
| 152 | +Returns: the number of attached files remaining in the field. |
| 153 | + |
| 154 | +## EWRetrieve |
| 155 | +GET/POST /ewws/EWRetrieve. Params: $KB,$table,$login,$password,id,field,filePosition |
| 156 | +Returns: file content in body. Content-Type = the type used when attaching. |
| 157 | + |
| 158 | +## EWLock |
| 159 | +GET (status) / PUT (lock) / DELETE (unlock) /ewws/EWLock |
| 160 | +Params: $KB,$table,$lang,id (+ $login/$password OR OAuth/JWT). `force` (any value) on DELETE only. |
| 161 | +Success JSON: {"id":18,"table_id":2788,"locked_by":"admin","lock_status":"LOCKED","lock_expires_in_minutes":25} |
| 162 | +Unlock: {"id":18,"table_id":2788,"lock_status":"NO_LOCK"} |
| 163 | +lock_status values: NO_LOCK | LOCKED |
| 164 | +Failure JSON: {error, error_description}; codes BAD_REQUEST/UNAUTHORIZED/FORBIDDEN/CONFLICT/SERVER_ERROR |
| 165 | + |
| 166 | +## EWGetChoiceLineId |
| 167 | +GET. Detail page URL: /ewws/EWGetChoiceLineId?$KB=..&$login=..&$password=..&$table=case&$lang=en&field=priority&value=High |
| 168 | +Returns: EWREST_choiceLineId = '1'; |
| 169 | +No match -> HTTP 400. |
| 170 | +Errors: 400 "No choice line found for value <fieldName>"; 500 unexpected |
| 171 | + |
| 172 | +## EWActionButton |
| 173 | +POST ONLY. URL: /ewws/async/EWActionButton?$KB=..&$login=..&$password=..&$lang=en&$table=case&name=ab_field&id=82 |
| 174 | +Returns: EWREST_id='82'; EWREST_EWCALLBACK_ID='10100_1'; |
| 175 | +Compatible with EWAsyncStatus. |
| 176 | +Errors: 400 "Wrong value for 'sequence' parameter"; 400 "No information for requested column <fieldName>" |
| 177 | + |
| 178 | +## EWAsyncStatus |
| 179 | +GET or POST /ewws/EWAsyncStatus. Params: $KB,$login,$password,$lang,$table,callback_id |
| 180 | +Returns response CODE only (empty body): 200 completed, 201 queued, 202 in progress, |
| 181 | + 501 failed, 523 no info for callback id. |
| 182 | + |
| 183 | +## EWSavedSearch |
| 184 | +GET/POST /ewws/EWSavedSearch/.json (JSON is the ONLY output; /.json is MANDATORY) |
| 185 | +URL must include the logical table name. For POST the table param may be in the body. |
| 186 | +MUST be used with EWLogin or OAuth 2.0 authorization. Never asynchronous. |
| 187 | +Example: https://localhost:8080/ewws/EWSavedSearch/.json?$table=contract |
| 188 | +Returns: {"success":true,"message":"","result":[{"label":"...","name":"...","id":265185,"description":""}]} |
| 189 | + |
| 190 | +## EWTable |
| 191 | +GET/POST /ewws/EWTable/.json. Requests x-www-form-urlencoded; returns application/json. |
| 192 | +MUST be used with EWLogin or OAuth 2.0 authorization. Never asynchronous. |
| 193 | +Params: $KB; optional `table` (plain, NOT $table) = logical name e.g. table=contacts; |
| 194 | + includelinkedinfo=true; skipColumnsInfo=true |
| 195 | +Example: https://localhost:8080/ewws/EWTable/.json?$KB=Demo&includelinkedinfo=true |
| 196 | +Returns: {"success":true,"message":"","result":{"tables":[{"label":"WMI Sample","logicalName":"wmi_sample", |
| 197 | + "fields":[{"columnLabel":"ID","columnName":"id","columnType":"BIGINT","columnTypeDomain":"swautoincrementfield"}, |
| 198 | + {"columnLabel":"Updated By","columnName":"_1794_full_name","columnType":"VARCHAR", |
| 199 | + "columnTypeDomain":"swshorttextfield","isLinked":true, |
| 200 | + "linkedInfo":[{"linkedTable":"contacts","linkedColumn":"full_name","linkedDao":"_dao3_link0"}], |
| 201 | + "textFieldType":"text/plain"}]}]}} |
| 202 | +Returns for fields: name, label, type, and required flag. Linked fields return only source table info. |
| 203 | +Action buttons, related tables, embedded search results, embedded communications NOT supported. |
| 204 | + |
| 205 | +## EWUpsert |
| 206 | +POST /ewws/EWUpsert. Content-Type application/x-www-form-urlencoded. |
| 207 | +Authentication: Required ($login and $password). |
| 208 | +Async support: Yes (EWAsyncStatus) via $async. |
| 209 | +System params: $KB*, $table*, $login*, $password*, $match*, $lang, $async |
| 210 | +Remaining params are record fields. |
| 211 | +Matching: no match -> create; one match -> update; multiple -> error. |
| 212 | +Example body: $KB=Demo / $table=contacts.employees / $login=admin / $password=qwerty / |
| 213 | + $lang=en / $match=_login / _login=jdoe / first_name=John / ... |
| 214 | +Returns: EWREST_id='353'; |
| 215 | +Status: 200 updated, 201 created, 202 accepted(async), 400, 401, 403, 404, |
| 216 | + 409 Conflict (multiple matching records), 500 |
| 217 | + |
| 218 | +## EWNLPSearch |
| 219 | +Content-Types: application/json, application/x-www-form-urlencoded |
| 220 | +Params: $KB*, $login*, $password*, $lang, field[]* , nlp_query*, page, limit |
| 221 | +Returns same format as REST-Search. |
| 222 | +Example return: {"success":true,"message":"","result":[{"company_name":"...","id":31,...}]} |
| 223 | + |
| 224 | +## DATA ENCODING |
| 225 | +- Choice fields: text value as in GUI (`&country=USA`). For EWSelect ad hoc queries use |
| 226 | + GetChoiceLineId IDs instead. |
| 227 | +- Multi-choice: repeated key/value pairs. |
| 228 | +- Elapsed time: "days:hours:minutes:seconds" e.g. "0:1:35:15" |
| 229 | +- Linked fields: Query By Example with ':' qualifier (`&company_name=:Agiloft` or |
| 230 | + `&company_name=Company:Agiloft`). ':' and '?' in values escaped with backslash. |
| 231 | + SQL sub-select form uses '?' qualifier. |
| 232 | +- File/image fields: POST with enctype multipart/form-data; form field name = file field name; |
| 233 | + `fieldName$overwrite` to replace rather than add. |
0 commit comments