@veryfi/veryfi-sdk 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,7 +41,7 @@ If you don't have an account with Veryfi, please go ahead and register here: [ht
41
41
 
42
42
  ### Node.js API Client Library
43
43
 
44
- The **veryfi** library can be used to communicate with Veryfi API. All available functionality is described here: <https://veryfi.github.io/veryfi-nodejs/Client.html>
44
+ The **veryfi** library can be used to communicate with Veryfi API. All available functionality is described here: <https://veryfi.github.io/veryfi-nodejs/>
45
45
 
46
46
  Below is a sample script using **Veryfi** for OCR and extracting data from a document:
47
47
 
@@ -251,4 +251,4 @@ If you found a bug in this library or would like new features added, then open a
251
251
 
252
252
  ## Tutorial Video
253
253
 
254
- [![Veryfi Tutorial](https://img.youtube.com/vi/PcJdgnvyfBc/maxresdefault.jpg)](https://www.youtube.com/watch?v=PcJdgnvyfBc)
254
+ [![Veryfi Tutorial](https://img.youtube.com/vi/PcJdgnvyfBc/maxresdefault.jpg)](https://www.youtube.com/watch?v=PcJdgnvyfBc)
package/lib/main.js CHANGED
@@ -2,7 +2,6 @@ const {createHmac} = require('crypto');
2
2
  const axios = require('axios').default;
3
3
  const path = require('path');
4
4
  const fs = require('fs');
5
- const VeryfiClientError = require('./errors');
6
5
 
7
6
  /**
8
7
  * Create instance of a Client
@@ -11,18 +10,18 @@ const VeryfiClientError = require('./errors');
11
10
  * @param {string} client_secret Your Veryfi client secret
12
11
  * @param {string} username Your Veryfi username
13
12
  * @param {string} api_key Your Veryfi API key
14
- * @param {string} base_url
15
- * @param {string} api_version
16
- * @param {Number} timeout
13
+ * @param {string} base_url
14
+ * @param {string} api_version
15
+ * @param {Number} timeout
17
16
  */
18
17
  function Client(
19
- client_id,
20
- client_secret,
21
- username,
22
- api_key,
23
- base_url="https://api.veryfi.com/api/",
24
- api_version="v7",
25
- timeout=120,) {
18
+ client_id,
19
+ client_secret,
20
+ username,
21
+ api_key,
22
+ base_url = "https://api.veryfi.com/",
23
+ api_version = "v8",
24
+ timeout = 120,) {
26
25
  this.client_id = client_id;
27
26
  this.client_secret = client_secret;
28
27
  this.username = username;
@@ -48,6 +47,14 @@ function Client(
48
47
  ];
49
48
  }
50
49
 
50
+ /**
51
+ * Check api version for w2 documents
52
+ * @private
53
+ * @throws if api_version is different to v8
54
+ */
55
+ Client.prototype._check_w2_version = function () {
56
+ if (this.api_version !== "v8") throw Error("w2 is only supported on v8")
57
+ }
51
58
 
52
59
  /**
53
60
  * Prepares the headers needed for a request.
@@ -55,15 +62,15 @@ function Client(
55
62
  * @param {Boolean} has_files Are there any files to be submitted as binary
56
63
  * @return {Object} Dictionary with headers
57
64
  */
58
- Client.prototype._get_headers = function (has_files=false){
65
+ Client.prototype._get_headers = function (has_files = false) {
59
66
  let final_headers = {
60
- "User-Agent": "Node.js Veryfi-Nodejs/1.1.4",
67
+ "User-Agent": "Node.js Veryfi-Nodejs/1.2.0",
61
68
  "Accept": "application/json",
62
69
  "Content-Type": "application/json",
63
70
  "Client-Id": this.client_id,
64
71
  "Authorization": `apikey ${this.username}:${this.api_key}`,
65
72
  };
66
- if (has_files){
73
+ if (has_files) {
67
74
  final_headers["Content-Type"] = "application/x-www-form-urlencoded";
68
75
  }
69
76
  return final_headers;
@@ -74,8 +81,8 @@ Client.prototype._get_headers = function (has_files=false){
74
81
  * @private
75
82
  * @returns {string} Base URL to Veryfi API
76
83
  */
77
- Client.prototype._get_url = function (){
78
- return this.base_url + this.api_version;
84
+ Client.prototype._get_url = function () {
85
+ return this.base_url + "api/" + this.api_version;
79
86
  }
80
87
 
81
88
  /**
@@ -85,9 +92,9 @@ Client.prototype._get_url = function (){
85
92
  * @param {Number} timestamp Unix Long timestamp
86
93
  * @returns {string} Unique signature generated using the client_secret and the payload
87
94
  */
88
- Client.prototype._generate_signature = function (payload_params, timestamp){
95
+ Client.prototype._generate_signature = function (payload_params, timestamp) {
89
96
  let payload = `timestamp:${timestamp}`;
90
- for (let i=0; i<Object.keys(payload_params).length; i++){
97
+ for (let i = 0; i < Object.keys(payload_params).length; i++) {
91
98
  let key = Object.keys(payload_params)[i];
92
99
  let value = payload_params[key];
93
100
  payload = `${payload},${key}:${value}`;
@@ -112,22 +119,24 @@ Client.prototype._generate_signature = function (payload_params, timestamp){
112
119
  * @param file_stream file stream of the document
113
120
  * @returns {JSON} A JSON of the response data.
114
121
  */
115
- Client.prototype._request = async function (http_verb, endpoint_name, request_arguments, file_stream=null){
122
+ Client.prototype._request = async function (http_verb, endpoint_name, request_arguments, file_stream = null) {
116
123
  let has_files = (Boolean(file_stream));
117
124
  let headers = this._get_headers(has_files);
118
125
  let api_url = `${this._get_url()}/partner${endpoint_name}`;
119
126
 
120
- if (this.client_secret){
127
+ if (this.client_secret) {
121
128
  let timestamp = Date.now();
122
129
  let signature = this._generate_signature(request_arguments, timestamp);
123
- headers = Object.assign(headers,{"X-Veryfi-Request-Timestamp": timestamp,
124
- "X-Veryfi-Request-Signature": signature});
130
+ headers = Object.assign(headers, {
131
+ "X-Veryfi-Request-Timestamp": timestamp,
132
+ "X-Veryfi-Request-Signature": signature
133
+ });
125
134
  }
126
135
 
127
136
  if (has_files === false) {
128
137
  request_arguments = JSON.stringify(request_arguments);
129
138
  } else {
130
- Object.assign(headers,{...request_arguments});
139
+ Object.assign(headers, {...request_arguments});
131
140
  }
132
141
 
133
142
  try {
@@ -139,9 +148,9 @@ Client.prototype._request = async function (http_verb, endpoint_name, request_ar
139
148
  timeout: this.timeout * 1000
140
149
  });
141
150
  } catch (response) {
142
- let Err = new VeryfiClientError(response,response['response']['data']);
143
- let err_msg = Err.from_response(response['response']);
144
- throw new Error(err_msg['status'] + err_msg['error']);
151
+ let errorStatus = response['response']['status'];
152
+ let errorInfo = response['response']['data']['error'];
153
+ throw new Error(errorStatus + errorInfo);
145
154
  }
146
155
  }
147
156
 
@@ -151,12 +160,12 @@ Client.prototype._request = async function (http_verb, endpoint_name, request_ar
151
160
  * @memberof Client
152
161
  * @returns {JSON} JSON object of previously processed documents
153
162
  */
154
- Client.prototype.get_documents = async function (){
163
+ Client.prototype.get_documents = async function () {
155
164
  let endpoint_name = "/documents/";
156
165
  let request_arguments = {};
157
166
  let documents = await this._request("GET", endpoint_name, request_arguments);
158
- if ("data" in documents){
159
- return documents["data"];
167
+ if ("data" in documents) {
168
+ documents = documents["data"];
160
169
  }
161
170
  return documents;
162
171
  }
@@ -178,10 +187,10 @@ Client.prototype.get_document = async function (document_id) {
178
187
  * Process a document and extract all the fields from it
179
188
  * @example
180
189
  * veryfi_client.process_document('file/path',
181
- * ['Entertainment','Food'],
182
- * true,
190
+ * ['Entertainment','Food'],
191
+ * true,
183
192
  * {"extra":"parameters"})
184
- *
193
+ *
185
194
  * @memberof Client
186
195
  * @param {String} file_path Path on disk to a file to submit for data extraction
187
196
  * @param {Array} categories List of categories Veryfi can use to categorize the document
@@ -190,14 +199,14 @@ Client.prototype.get_document = async function (document_id) {
190
199
  * @returns {JSON} Data extracted from the document
191
200
  */
192
201
  Client.prototype.process_document = async function (
193
- file_path,
194
- categories = null,
195
- delete_after_processing = false,
196
- {...kwargs} = {}
197
- ) {
198
-
202
+ file_path,
203
+ categories = null,
204
+ delete_after_processing = false,
205
+ {...kwargs} = {}
206
+ ) {
207
+
199
208
  let endpoint_name = "/documents/";
200
- if (!categories){
209
+ if (!categories) {
201
210
  categories = this.CATEGORIES;
202
211
  }
203
212
  let file_name = path.basename(file_path)
@@ -209,7 +218,7 @@ Client.prototype.process_document = async function (
209
218
  "categories": categories,
210
219
  "auto_delete": delete_after_processing,
211
220
  };
212
- request_arguments = Object.assign(request_arguments,kwargs)
221
+ request_arguments = Object.assign(request_arguments, kwargs)
213
222
  let document = await this._request("POST", endpoint_name, request_arguments)
214
223
  return document['data'];
215
224
  }
@@ -219,10 +228,10 @@ Client.prototype.process_document = async function (
219
228
  * @example
220
229
  * veryfi_client.process_document_buffer('base64_encoded_string',
221
230
  * 'receipt.png',
222
- * ['Entertainment','Food'],
223
- * true,
231
+ * ['Entertainment','Food'],
232
+ * true,
224
233
  * {'extra': 'parameters'})
225
- *
234
+ *
226
235
  * @memberof Client
227
236
  * @param {String} base64_encoded_string Buffer of a file to submit for data extraction
228
237
  * @param {String} file_name The file name including the extension
@@ -232,15 +241,15 @@ Client.prototype.process_document = async function (
232
241
  * @returns {JSON} Data extracted from the document
233
242
  */
234
243
  Client.prototype.process_document_buffer = async function (
235
- base64_encoded_string,
236
- file_name,
237
- categories = null,
238
- delete_after_processing = false,
239
- {...kwargs} = {}
240
- ) {
241
-
244
+ base64_encoded_string,
245
+ file_name,
246
+ categories = null,
247
+ delete_after_processing = false,
248
+ {...kwargs} = {}
249
+ ) {
250
+
242
251
  let endpoint_name = "/documents/";
243
- if (!categories){
252
+ if (!categories) {
244
253
  categories = this.CATEGORIES;
245
254
  }
246
255
  let request_arguments = {
@@ -249,7 +258,7 @@ Client.prototype.process_document_buffer = async function (
249
258
  "categories": categories,
250
259
  "auto_delete": delete_after_processing,
251
260
  };
252
- request_arguments = Object.assign(request_arguments,kwargs)
261
+ request_arguments = Object.assign(request_arguments, kwargs)
253
262
  let document = await this._request("POST", endpoint_name, request_arguments)
254
263
  return document['data'];
255
264
  }
@@ -271,17 +280,17 @@ Client.prototype.process_document_buffer = async function (
271
280
  * @return {JSON} Data extracted from the document.
272
281
  */
273
282
  Client.prototype.process_document_url = async function (
274
- file_url = "",
275
- file_urls = null,
276
- categories = null,
277
- delete_after_processing = false,
278
- boost_mode = 0,
279
- external_id = "",
280
- max_pages_to_process = 1,
281
- {...kwargs} = {},
282
- ) {
283
+ file_url = "",
284
+ file_urls = null,
285
+ categories = null,
286
+ delete_after_processing = false,
287
+ boost_mode = 0,
288
+ external_id = "",
289
+ max_pages_to_process = 1,
290
+ {...kwargs} = {},
291
+ ) {
283
292
  let endpoint_name = "/documents/";
284
- if (!categories){
293
+ if (!categories) {
285
294
  categories = this.CATEGORIES;
286
295
  }
287
296
  let request_arguments = {
@@ -293,40 +302,158 @@ Client.prototype.process_document_url = async function (
293
302
  "file_urls": file_urls,
294
303
  "max_pages_to_process": max_pages_to_process,
295
304
  };
296
- request_arguments = Object.assign(request_arguments,kwargs)
305
+ request_arguments = Object.assign(request_arguments, kwargs)
297
306
  let response = await this._request("POST", endpoint_name, request_arguments);
298
307
  return response['data'];
299
308
  }
300
309
 
301
310
  /**
302
311
  * Delete document from Veryfi
303
- *
312
+ *
304
313
  * @memberof Client
305
314
  * @param {string} document_id ID of the document you'd like to delete
306
315
  */
307
- Client.prototype.delete_document = async function (document_id){
316
+ Client.prototype.delete_document = async function (document_id) {
308
317
  let endpoint_name = `/documents/${document_id}/`;
309
318
  let request_arguments = {"id": document_id};
310
- let response = await this._request("DELETE", endpoint_name, request_arguments);
311
- return response;
319
+ return this._request("DELETE", endpoint_name, request_arguments);
312
320
  }
313
321
 
314
322
  /**
315
323
  * Update data for a previously processed document, including almost any field like `vendor`, `date`, `notes` and etc.
316
324
  * @example
317
325
  * veryfi_client.update_document(id, {date:"2021-01-01", notes:"look what I did"})
318
- *
326
+ *
319
327
  * @memberof Client
320
328
  * @param {string} document_id ID of the document you'd like to update
321
329
  * @param {Object} kwargs fields to update
322
330
  * @return {JSON} A document json with updated fields, if fields are writable. Otherwise a document with unchanged fields.
323
331
  */
324
- Client.prototype.update_document = async function (document_id, {...kwargs} = {}){
332
+ Client.prototype.update_document = async function (document_id, {...kwargs} = {}) {
325
333
  let endpoint_name = `/documents/${document_id}/`;
326
334
  let response = await this._request("PUT", endpoint_name, kwargs);
327
335
  return response['data'];
328
336
  }
329
337
 
338
+ /**
339
+ * Get all w2 documents.
340
+ * @memberOf Client
341
+ * @return {Array} An array of JSON with all w2 documents.
342
+ */
343
+ Client.prototype.get_w2_documents = async function () {
344
+ this._check_w2_version()
345
+ let endpoint_name = "/w2s/"
346
+ let request_arguments = {}
347
+ let response = await this._request("GET", endpoint_name, request_arguments)
348
+ return response['data']['results']
349
+ }
350
+
351
+ /**
352
+ * Get a w2 document
353
+ * @memberOf Client
354
+ * @param {string} document_id ID of the document you'd like to retrieve
355
+ * @returns {JSON} Data extracted from the Document
356
+ */
357
+ Client.prototype.get_w2_document = async function (
358
+ document_id,
359
+ ) {
360
+ this._check_w2_version()
361
+ let endpoint_name = `/w2s/${document_id}/`
362
+ let request_arguments = {"id": document_id}
363
+ let response = await this._request("GET", endpoint_name, request_arguments)
364
+ return response['data']
365
+ }
366
+
367
+ /**
368
+ * Upload a document from a buffer.
369
+ * @memberOf Client
370
+ * @param {String} file_name The file name including the extension
371
+ * @param {String} file_buffer Buffer of a file to submit for data extraction
372
+ * @param {boolean} delete_after_processing Delete this document from Veryfi after data has been extracted
373
+ * @param {int} max_pages_to_process When sending a long document to Veryfi for processing, this parameter controls how many pages of the document will be read and processed, starting from page 1.
374
+ * @param {Object} kwargs Additional request parameters
375
+ * @return {JSON} Data extracted from the document.
376
+ */
377
+ Client.prototype.process_w2_document_from_buffer = async function (
378
+ file_name,
379
+ file_buffer,
380
+ delete_after_processing = null,
381
+ max_pages_to_process = null,
382
+ {...kwargs} = {}
383
+ ) {
384
+ this._check_w2_version()
385
+ let endpoint_name = "/w2s/"
386
+ let request_arguments = {
387
+ "file_name": file_name,
388
+ "file_data": file_buffer,
389
+ "auto_delete": delete_after_processing,
390
+ "max_pages_to_process": max_pages_to_process,
391
+ }
392
+ request_arguments = Object.assign(request_arguments, kwargs)
393
+ let response = await this._request("POST", endpoint_name, request_arguments)
394
+ return response['data']
395
+ }
396
+
397
+ /**
398
+ * Upload a document from a file path
399
+ * @param {String} file_path Path on disk to a file to submit for data extraction
400
+ * @param {boolean} delete_after_processing Delete this document from Veryfi after data has been extracted
401
+ * @param {int} max_pages_to_process When sending a long document to Veryfi for processing, this parameter controls how many pages of the document will be read and processed, starting from page 1.
402
+ * @param {Object} kwargs Additional request parameters
403
+ * @return {JSON} Data extracted from the document.
404
+ */
405
+ Client.prototype.process_w2_document = async function (
406
+ file_path,
407
+ delete_after_processing = false,
408
+ max_pages_to_process = 1,
409
+ {...kwargs} = {}
410
+ ) {
411
+ const file_name = path.basename(file_path)
412
+ const image_file = fs.readFileSync(file_path, {encoding: 'base64'})
413
+ const base64_encoded_string = Buffer.from(image_file).toString('utf-8')
414
+ return this.process_w2_document_from_buffer(
415
+ file_name,
416
+ base64_encoded_string,
417
+ delete_after_processing,
418
+ max_pages_to_process,
419
+ kwargs
420
+ )
421
+ }
422
+
423
+ /**
424
+ * Process a w2 document from an url.
425
+ * @memberOf Client
426
+ * @param {String} file_name The file name including the extension
427
+ * @memberof Client
428
+ * @param {string} file_url Required if file_urls isn't specified. Publicly accessible URL to a file, e.g. "https://cdn.example.com/receipt.jpg".
429
+ * @param {Array} file_urls Required if file_url isn't specified. List of publicly accessible URLs to multiple files, e.g. ["https://cdn.example.com/receipt1.jpg", "https://cdn.example.com/receipt2.jpg"]
430
+ * @param {boolean} delete_after_processing Delete this document from Veryfi after data has been extracted
431
+ * @param {int} max_pages_to_process When sending a long document to Veryfi for processing, this parameter controls how many pages of the document will be read and processed, starting from page 1.
432
+ * @param {Object} kwargs Additional request parameters
433
+ * @return {JSON} Data extracted from the document.
434
+ */
435
+ Client.prototype.process_w2_document_from_url = async function (
436
+ file_name,
437
+ file_url,
438
+ file_urls = null,
439
+ delete_after_processing = false,
440
+ max_pages_to_process = 1,
441
+ {...kwargs} = {}
442
+ ) {
443
+ this._check_w2_version()
444
+ let endpoint_name = "/w2s/"
445
+ let request_arguments = {
446
+ "file_name": file_name,
447
+ "auto_delete": delete_after_processing,
448
+ "file_url": file_url,
449
+ "file_urls": file_urls,
450
+ "max_pages_to_process": max_pages_to_process
451
+ }
452
+ request_arguments = Object.assign(request_arguments, kwargs)
453
+ let response = await this._request("POST", endpoint_name, request_arguments)
454
+ return response['data']
455
+ }
456
+
330
457
  // Exports
331
458
 
332
459
  module.exports = Client;
@@ -40,6 +40,7 @@ export declare type VeryfiDocument = {
40
40
  notes?: null | string;
41
41
  ocr_text?: null | string;
42
42
  order_date?: null | string;
43
+ payment?: null | Payment;
43
44
  payment_display_name?: null | string;
44
45
  payment_terms?: null | string;
45
46
  payment_type?: null | string;
@@ -114,6 +115,13 @@ declare type Vendor = {
114
115
  web?: null | string;
115
116
  };
116
117
 
118
+ declare type Payment = {
119
+ card_number?: null | string;
120
+ display_name?: null | string;
121
+ terms?: null | number;
122
+ type?: null | string;
123
+ };
124
+
117
125
  export declare class Client {
118
126
  /**
119
127
  * Create instance of a Client
package/package.json CHANGED
@@ -1,29 +1,41 @@
1
1
  {
2
2
  "name": "@veryfi/veryfi-sdk",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "Node.js module for communicating with the Veryfi OCR API",
5
5
  "main": "lib/main.js",
6
+ "typings": "types/main.d.ts",
6
7
  "scripts": {
7
8
  "test": "jest",
8
9
  "doc": "jsdoc -d docs --configure jsconf.json main.js",
9
- "generate-docs": "jsdoc --configure .jsdoc.json --verbose"
10
+ "generate-docs": "jsdoc --configure jsdoc.json --verbose"
10
11
  },
11
12
  "author": "Veryfi <support@veryfi.com> (https://www.veryfi.com)",
12
13
  "homepage": "https://veryfi.github.io/veryfi-nodejs/",
13
14
  "contributors": [
14
- "Matthew Eng <matthew@veryfi.com>"
15
+ "Matthew Eng <matthew@veryfi.com>",
16
+ "Alejandro Uribe <alejandro@veryfi.com>"
15
17
  ],
16
18
  "license": "MIT",
19
+ "files": [
20
+ "lib",
21
+ "lib/types"
22
+ ],
17
23
  "directories": {
18
24
  "lib": "lib",
19
25
  "test": "test"
20
26
  },
21
27
  "devDependencies": {
22
- "jest": "^27.0.5",
23
- "jsdoc": "^3.6.7"
28
+ "jest": "^29.0.0",
29
+ "jsdoc": "^3.6.7",
30
+ "minami": "^1.2.3",
31
+ "ts-jest": "^29.0.1",
32
+ "typescript": "^4.8.3"
24
33
  },
25
34
  "dependencies": {
26
- "axios": "^0.21.1"
35
+ "@jest/globals": "^29.0.3",
36
+ "axios": "^0.21.1",
37
+ "docdash": "^1.2.0",
38
+ "jest-config": "^29.0.3"
27
39
  },
28
40
  "repository": {
29
41
  "type": "git",
@@ -1,31 +0,0 @@
1
- # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2
- # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3
-
4
- name: Node.js CI
5
-
6
- on:
7
- push:
8
- branches: [ main ]
9
- pull_request:
10
- branches: [ main ]
11
-
12
- jobs:
13
- build:
14
-
15
- runs-on: ubuntu-latest
16
-
17
- strategy:
18
- matrix:
19
- node-version: [12.x, 14.x, 16.x]
20
- # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
21
-
22
- steps:
23
- - uses: actions/checkout@v2
24
- - name: Use Node.js ${{ matrix.node-version }}
25
- uses: actions/setup-node@v2
26
- with:
27
- node-version: ${{ matrix.node-version }}
28
- cache: 'npm'
29
- - run: npm ci
30
- - run: npm run build --if-present
31
- - run: npm test
package/lib/errors.js DELETED
@@ -1,36 +0,0 @@
1
- let VeryfiClientError = function (raw_response, error_info) {
2
- this.raw_response = raw_response['response'];
3
- this.status = this.raw_response['status'];
4
- this.error_info = error_info['error']
5
- }
6
-
7
-
8
- /** Veryfi API returns error messages with a json body
9
- * like:
10
- * {
11
- * 'status': 'fail',
12
- * 'error': 'Human readable error description.'
13
- * }
14
- */
15
- VeryfiClientError.prototype.from_response = function (raw_response){
16
- try{
17
- error_cls = _error_map[this.status]
18
- } catch (KeyError) {
19
- console.error(
20
- "Unknown error Please contact customer support at support@veryfi.com."
21
- )
22
- }
23
-
24
- return {'status':error_cls, 'error':this.error_info}
25
- }
26
-
27
- _error_map = {
28
- 400: 'BadRequest',
29
- 401: 'UnauthorizedAccessToken',
30
- 404: 'NotFound',
31
- 405: 'UnexpectedHTTPMethod',
32
- 409: 'AccessLimitReached',
33
- 500: 'InternalError',
34
- }
35
-
36
- module.exports = VeryfiClientError;
@@ -1,4 +0,0 @@
1
- {
2
- "status":"ok",
3
- "message":"Document has been deleted"
4
- }