veryfi 3.0.0 → 4.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +1 -1
- data/.github/workflows/test.yml +1 -1
- data/.gitignore +4 -1
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -1
- data/.yardopts +10 -0
- data/Gemfile.lock +55 -56
- data/README.md +530 -2
- data/Rakefile +21 -0
- data/lib/veryfi/api/any_document.rb +123 -0
- data/lib/veryfi/api/bank_statement.rb +114 -0
- data/lib/veryfi/api/bank_statement_split.rb +66 -0
- data/lib/veryfi/api/business_card.rb +84 -0
- data/lib/veryfi/api/check.rb +127 -0
- data/lib/veryfi/api/classify.rb +53 -0
- data/lib/veryfi/api/document.rb +117 -0
- data/lib/veryfi/api/document_tag.rb +43 -0
- data/lib/veryfi/api/file_payload.rb +23 -0
- data/lib/veryfi/api/line_item.rb +55 -0
- data/lib/veryfi/api/pdf_split.rb +75 -0
- data/lib/veryfi/api/tag.rb +14 -0
- data/lib/veryfi/api/tag_operations.rb +63 -0
- data/lib/veryfi/api/tax_line.rb +71 -0
- data/lib/veryfi/api/w2.rb +90 -0
- data/lib/veryfi/api/w2_split.rb +68 -0
- data/lib/veryfi/api/w8.rb +90 -0
- data/lib/veryfi/api/w9.rb +92 -0
- data/lib/veryfi/client.rb +61 -17
- data/lib/veryfi/configuration.rb +28 -0
- data/lib/veryfi/error.rb +98 -12
- data/lib/veryfi/request.rb +22 -11
- data/lib/veryfi/resource.rb +102 -0
- data/lib/veryfi/version.rb +1 -1
- data/lib/veryfi.rb +64 -0
- data/veryfi.gemspec +24 -2
- metadata +40 -8
data/README.md
CHANGED
|
@@ -17,9 +17,33 @@
|
|
|
17
17
|
- [Table of Contents](#table-of-contents)
|
|
18
18
|
- [Example](#example)
|
|
19
19
|
- [Installation](#installation)
|
|
20
|
+
- [Versioning & compatibility](#versioning--compatibility)
|
|
20
21
|
- [Getting Started](#getting-started)
|
|
21
22
|
- [Obtaining Client ID and user keys](#obtaining-client-id-and-user-keys)
|
|
22
23
|
- [Ruby API Client Library](#ruby-api-client-library)
|
|
24
|
+
- [Configuring the client](#configuring-the-client)
|
|
25
|
+
- [Custom Faraday configuration](#custom-faraday-configuration)
|
|
26
|
+
- [Handling errors](#handling-errors)
|
|
27
|
+
- [Response objects](#response-objects)
|
|
28
|
+
- [Common parameters & defaults](#common-parameters--defaults)
|
|
29
|
+
- [Available APIs](#available-apis)
|
|
30
|
+
- [Documents](#documents)
|
|
31
|
+
- [Tags](#tags)
|
|
32
|
+
- [Document Tags](#document-tags)
|
|
33
|
+
- [Line Items](#line-items)
|
|
34
|
+
- [Tax Lines](#tax-lines)
|
|
35
|
+
- [PDF Split (Documents Set)](#pdf-split-documents-set)
|
|
36
|
+
- [Any Document (A-Docs)](#any-document-a-docs)
|
|
37
|
+
- [Bank Statements](#bank-statements)
|
|
38
|
+
- [Bank Statement Split](#bank-statement-split)
|
|
39
|
+
- [Business Cards](#business-cards)
|
|
40
|
+
- [Checks](#checks)
|
|
41
|
+
- [Classify](#classify)
|
|
42
|
+
- [W-2](#w-2)
|
|
43
|
+
- [W-2 Split](#w-2-split)
|
|
44
|
+
- [W-8 BEN-E](#w-8-ben-e)
|
|
45
|
+
- [W-9](#w-9)
|
|
46
|
+
- [Per-resource tags](#per-resource-tags)
|
|
23
47
|
- [Need help?](#need-help)
|
|
24
48
|
- [For Developers](#for-developers)
|
|
25
49
|
- [Install](#install)
|
|
@@ -225,13 +249,80 @@ This will produce the following response:
|
|
|
225
249
|
|
|
226
250
|
## Installation
|
|
227
251
|
|
|
252
|
+
Install the latest version of the gem:
|
|
253
|
+
|
|
228
254
|
```bash
|
|
229
255
|
gem install veryfi
|
|
230
256
|
```
|
|
231
257
|
|
|
232
|
-
Or
|
|
258
|
+
Or pin it in your `Gemfile`. The current major series is **`4.x`**, so the
|
|
259
|
+
recommended pessimistic constraint is:
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
gem 'veryfi', '~> 4.0'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
That gives you all backwards-compatible improvements in the `4.x` line
|
|
266
|
+
(`>= 4.0, < 5.0`) without unexpectedly jumping to a future `5.0` that
|
|
267
|
+
might contain breaking changes.
|
|
268
|
+
|
|
269
|
+
After editing your `Gemfile`, run:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
bundle install
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Then in your Ruby code:
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
require 'veryfi'
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Versioning & compatibility
|
|
282
|
+
|
|
283
|
+
`veryfi-ruby` follows [Semantic Versioning](https://semver.org/):
|
|
284
|
+
|
|
285
|
+
- **MAJOR** (`4.x` → `5.x`): backwards-incompatible API changes. Read the
|
|
286
|
+
release notes before upgrading.
|
|
287
|
+
- **MINOR** (`4.0.x` → `4.1.0`): new endpoints or new methods, fully
|
|
288
|
+
backwards compatible. Safe to upgrade.
|
|
289
|
+
- **PATCH** (`4.0.0` → `4.0.1`): bug fixes only. Safe to upgrade.
|
|
290
|
+
|
|
291
|
+
| Series | Status | Notes |
|
|
292
|
+
| ------- | ----------- | ------------------------------------------------------------------------------------ |
|
|
293
|
+
| `4.x` | **Current** | Full coverage of the Veryfi v8 partner API including A-Docs, bank statements, checks (with remittance + async), W-2/W-8/W-9, classify, PDF split, W-2 split, bank-statement split, tax lines, and per-resource tag management. Responses are lightweight `Veryfi::Resource` objects (Hash-compatible). |
|
|
294
|
+
| `3.x` | Maintenance | Documents, line items, tags, document tags only. |
|
|
295
|
+
| `<=2.x` | Unsupported | Please upgrade. |
|
|
296
|
+
|
|
297
|
+
### Supported Ruby versions
|
|
298
|
+
|
|
299
|
+
The minimum supported Ruby version is **3.0** (the floor of the Faraday
|
|
300
|
+
2.x line, which is the gem's only non-stdlib runtime dependency). CI
|
|
301
|
+
verifies the gem against:
|
|
302
|
+
|
|
303
|
+
| Ruby | Upstream status | Notes |
|
|
304
|
+
| ------ | ---------------------------- | -------------------------------------- |
|
|
305
|
+
| `3.0` | End-of-life upstream | Floor — best-effort, no Ruby-side fixes |
|
|
306
|
+
| `3.1` | End-of-life upstream | Best-effort |
|
|
307
|
+
| `3.2` | Security maintenance | |
|
|
308
|
+
| `3.3` | Normal maintenance | |
|
|
309
|
+
| `3.4` | Normal maintenance | |
|
|
310
|
+
| `4.0` | Current stable | |
|
|
311
|
+
|
|
312
|
+
Ruby 2.7 and earlier are not supported. If you need to stay on Ruby 2.7
|
|
313
|
+
pin the `veryfi` 3.x release line, which targeted that vintage of Ruby.
|
|
314
|
+
|
|
315
|
+
The gem talks to Veryfi API version **`v8`** by default. You can override
|
|
316
|
+
this at construction time if you are working against a different version:
|
|
317
|
+
|
|
233
318
|
```ruby
|
|
234
|
-
|
|
319
|
+
Veryfi::Client.new(
|
|
320
|
+
client_id: 'your_client_id',
|
|
321
|
+
client_secret: 'your_client_secret',
|
|
322
|
+
username: 'your_username',
|
|
323
|
+
api_key: 'your_api_key',
|
|
324
|
+
api_version: 'v8' # default
|
|
325
|
+
)
|
|
235
326
|
```
|
|
236
327
|
|
|
237
328
|
## Getting Started
|
|
@@ -244,6 +335,443 @@ If you don't have an account with Veryfi, please go ahead and register here: [ht
|
|
|
244
335
|
|
|
245
336
|
The **veryfi-ruby** gem can be used to communicate with Veryfi API. All available functionality is described [in docs](https://veryfi.github.io/veryfi-ruby/)
|
|
246
337
|
|
|
338
|
+
## Configuring the client
|
|
339
|
+
|
|
340
|
+
The most explicit way is to instantiate {`Veryfi::Client`} directly:
|
|
341
|
+
|
|
342
|
+
```ruby
|
|
343
|
+
client = Veryfi::Client.new(
|
|
344
|
+
client_id: ENV.fetch('VERYFI_CLIENT_ID'),
|
|
345
|
+
client_secret: ENV.fetch('VERYFI_CLIENT_SECRET'),
|
|
346
|
+
username: ENV.fetch('VERYFI_USERNAME'),
|
|
347
|
+
api_key: ENV.fetch('VERYFI_API_KEY')
|
|
348
|
+
)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
For apps that want a single process-wide client (common in Rails / Sidekiq
|
|
352
|
+
setups), the `Veryfi.configure` / `Veryfi.client` shortcuts are provided:
|
|
353
|
+
|
|
354
|
+
```ruby
|
|
355
|
+
# config/initializers/veryfi.rb
|
|
356
|
+
Veryfi.configure do |c|
|
|
357
|
+
c.client_id = ENV.fetch('VERYFI_CLIENT_ID')
|
|
358
|
+
c.client_secret = ENV.fetch('VERYFI_CLIENT_SECRET')
|
|
359
|
+
c.username = ENV.fetch('VERYFI_USERNAME')
|
|
360
|
+
c.api_key = ENV.fetch('VERYFI_API_KEY')
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# anywhere in your app
|
|
364
|
+
Veryfi.client.document.process(file_path: './receipt.jpg')
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
`Veryfi.client` is memoized; if you re-`configure` the SDK it's rebuilt
|
|
368
|
+
automatically on the next access. Call `Veryfi.reset!` in tests to drop
|
|
369
|
+
the memoized client and configuration.
|
|
370
|
+
|
|
371
|
+
### Custom Faraday configuration
|
|
372
|
+
|
|
373
|
+
The underlying HTTP connection is a plain `Faraday::Connection`. Pass a
|
|
374
|
+
`faraday:` block to add middleware — retries, logging, persistent
|
|
375
|
+
connections, anything Faraday supports:
|
|
376
|
+
|
|
377
|
+
```ruby
|
|
378
|
+
client = Veryfi::Client.new(
|
|
379
|
+
client_id: '…',
|
|
380
|
+
client_secret: '…',
|
|
381
|
+
username: '…',
|
|
382
|
+
api_key: '…',
|
|
383
|
+
faraday: ->(conn) {
|
|
384
|
+
# automatic exponential backoff on retryable statuses
|
|
385
|
+
conn.request :retry,
|
|
386
|
+
max: 3,
|
|
387
|
+
interval: 0.5,
|
|
388
|
+
backoff_factor: 2,
|
|
389
|
+
retry_statuses: [429, 502, 503, 504]
|
|
390
|
+
|
|
391
|
+
# log every request / response
|
|
392
|
+
conn.response :logger, Rails.logger if defined?(Rails)
|
|
393
|
+
|
|
394
|
+
# keep TCP connections open between API calls
|
|
395
|
+
conn.adapter :net_http_persistent
|
|
396
|
+
}
|
|
397
|
+
)
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
(`faraday-retry` and `faraday-net_http_persistent` are not bundled with
|
|
401
|
+
this gem — install whichever extensions you need.)
|
|
402
|
+
|
|
403
|
+
## Handling errors
|
|
404
|
+
|
|
405
|
+
Every error raised by the SDK descends from `Veryfi::Error::VeryfiError`,
|
|
406
|
+
so a catch-all rescue is always valid:
|
|
407
|
+
|
|
408
|
+
```ruby
|
|
409
|
+
begin
|
|
410
|
+
client.document.process(file_path: './receipt.jpg')
|
|
411
|
+
rescue Veryfi::Error::VeryfiError => e
|
|
412
|
+
Rails.logger.error("Veryfi call failed (status=#{e.status}): #{e.message}")
|
|
413
|
+
raise
|
|
414
|
+
end
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
When you want to react differently per HTTP status, rescue one of the
|
|
418
|
+
specific subclasses. Order matters — list narrower classes before broader
|
|
419
|
+
ones:
|
|
420
|
+
|
|
421
|
+
| HTTP status | Exception class | Typical reason |
|
|
422
|
+
| ------------------ | --------------------------------------- | ------------------------------------------- |
|
|
423
|
+
| `400 Bad Request` | `Veryfi::Error::BadRequest` | Malformed payload or failed validation |
|
|
424
|
+
| `401 Unauthorized` | `Veryfi::Error::Unauthorized` | Bad / missing / expired credentials |
|
|
425
|
+
| `403 Forbidden` | `Veryfi::Error::AccessLimitReached` | Credentials lack permission for this action |
|
|
426
|
+
| `404 Not Found` | `Veryfi::Error::NotFound` | Resource id does not exist |
|
|
427
|
+
| `408 Request Timeout` | `Veryfi::Error::RequestTimeout` | Request timed out before Veryfi responded |
|
|
428
|
+
| `409 Conflict` | `Veryfi::Error::Conflict` | Conflicts with current resource state |
|
|
429
|
+
| `415 Unsupported Media` | `Veryfi::Error::UnsupportedMediaType` | File type not supported by the endpoint |
|
|
430
|
+
| `429 Too Many Requests` | `Veryfi::Error::TooManyRequests` | Rate-limited; back off and retry |
|
|
431
|
+
| Other 4xx | `Veryfi::Error::ClientError` | Generic 4xx |
|
|
432
|
+
| Any 5xx | `Veryfi::Error::ServerError` | Server-side error; retry with backoff |
|
|
433
|
+
|
|
434
|
+
```ruby
|
|
435
|
+
begin
|
|
436
|
+
client.document.process(file_path: path)
|
|
437
|
+
rescue Veryfi::Error::Unauthorized then refresh_credentials!
|
|
438
|
+
rescue Veryfi::Error::TooManyRequests then back_off
|
|
439
|
+
rescue Veryfi::Error::ServerError then schedule_retry
|
|
440
|
+
rescue Veryfi::Error::VeryfiError then notify_ops
|
|
441
|
+
end
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Each error exposes `#status` (Integer), `#response` (parsed body as a
|
|
445
|
+
`Veryfi::Resource`) and `#message` (the pretty-printed JSON body, falling
|
|
446
|
+
back to `"<status>"` when the response is empty).
|
|
447
|
+
|
|
448
|
+
## Response objects
|
|
449
|
+
|
|
450
|
+
Every API call returns a `Veryfi::Resource`. A `Resource` is a tiny
|
|
451
|
+
subclass of `Hash`, so anything that already treats the response as a
|
|
452
|
+
hash keeps working unchanged — no migration required when upgrading
|
|
453
|
+
from earlier versions of this gem:
|
|
454
|
+
|
|
455
|
+
```ruby
|
|
456
|
+
response = client.document.get(44_691_518)
|
|
457
|
+
|
|
458
|
+
response["id"] # => 44691518
|
|
459
|
+
response[:id] # => 44691518 (symbol keys work too)
|
|
460
|
+
response.dig("vendor", "name") # => "East Repair"
|
|
461
|
+
response.is_a?(Hash) # => true
|
|
462
|
+
JSON.pretty_generate(response) # works as you'd expect
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
In addition, every key is exposed as a method, recursively:
|
|
466
|
+
|
|
467
|
+
```ruby
|
|
468
|
+
response.id # => 44691518
|
|
469
|
+
response.vendor.name # => "East Repair"
|
|
470
|
+
response.line_items.first.description # => "Brake cables"
|
|
471
|
+
response.line_items.map(&:total) # => [100, 30, 15]
|
|
472
|
+
response.is_duplicate? # => true (boolean predicate sugar)
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Nested objects become `Resource`s and arrays of objects become arrays
|
|
476
|
+
of `Resource`s automatically. Leaf values (strings, numbers, booleans,
|
|
477
|
+
`nil`) pass through untouched. Unknown keys raise `NoMethodError`, so
|
|
478
|
+
typos surface immediately instead of silently returning `nil`.
|
|
479
|
+
|
|
480
|
+
If you need a plain `Hash` (e.g. to hand off to a serializer that
|
|
481
|
+
inspects the exact class), call `#to_h`, which recursively unwraps:
|
|
482
|
+
|
|
483
|
+
```ruby
|
|
484
|
+
response.to_h.class # => Hash
|
|
485
|
+
response.to_h["vendor"].class # => Hash
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Common parameters & defaults
|
|
489
|
+
|
|
490
|
+
Most of the "process" methods (`process`, `process_url`, `process_async`,
|
|
491
|
+
`process_url_async`, `process_with_remittance`, …) accept the same set
|
|
492
|
+
of optional keys. **Omitting a key is exactly equivalent to passing its
|
|
493
|
+
default value** — both produce the same outbound request. Only pass a
|
|
494
|
+
key when you want a non-default value or want to make the intent
|
|
495
|
+
explicit in your own code.
|
|
496
|
+
|
|
497
|
+
| Key | Required? | Default | Meaning |
|
|
498
|
+
| ----------------------- | ------------------------------------------ | --------------------------------------------- | ------- |
|
|
499
|
+
| `file_path` | Yes for `process` / `process_async` etc. | — | Local path to the file to upload. Read and base64-encoded for you. |
|
|
500
|
+
| `file_url` | Yes for `process_url` (or `file_urls`) | — | Publicly accessible URL to a single file. |
|
|
501
|
+
| `file_urls` | Alternative to `file_url` | — | Array of publicly accessible URLs treated as one logical document. |
|
|
502
|
+
| `file_name` | No | basename of `file_path` / `file_url` | Display name sent to Veryfi. Useful when `file_path` is a tempfile with an ugly name. |
|
|
503
|
+
| `categories` | No | Veryfi's default list (see `Veryfi::Api::Document::CATEGORIES`) for receipts/invoices; `[]` for split endpoints | Restrict Veryfi's categorization output to this set of strings. |
|
|
504
|
+
| `tags` | No | `nil` (no tags) | Array of tag names to attach to the resulting document. |
|
|
505
|
+
| `auto_delete` | No | `false` | When `true`, Veryfi deletes the document from its storage immediately after extraction. Use when you don't need Veryfi to keep the file (e.g. you store it yourself). |
|
|
506
|
+
| `boost_mode` | No | `false` | When `true`, Veryfi skips data-enrichment steps (vendor lookup, logo, category enrichment, etc.). Processing is **faster** but the response has **less** extracted/enriched data. Useful for high-throughput pipelines that don't need the extras. |
|
|
507
|
+
| `async` | No | `false` | When `true`, the request returns immediately (with a processing-status payload) and Veryfi continues extraction in the background. **Prefer the dedicated `.process_async` / `.process_url_async` methods** where available — they hit the canonical async endpoint instead of piggybacking on the sync one. |
|
|
508
|
+
| `external_id` | No | `nil` | Your own identifier for the document. Echoed back in the response and searchable via `client.document.all(external_id: …)`. |
|
|
509
|
+
| `max_pages_to_process` | No | `nil` (= all pages) | Hard cap on the number of pages Veryfi reads, starting from page 1. Useful for very long PDFs when you only care about the first few pages. |
|
|
510
|
+
| `bounding_boxes` | No | `false` | When `true`, the response includes `bounding_box` / `bounding_region` metadata for each extracted field. |
|
|
511
|
+
| `confidence_details` | No | `false` | When `true`, the response includes per-field `score` and `ocr_score` values. |
|
|
512
|
+
|
|
513
|
+
So all four of the following calls are equivalent and produce the same
|
|
514
|
+
request payload — pick whichever style your team prefers:
|
|
515
|
+
|
|
516
|
+
```ruby
|
|
517
|
+
# All defaults explicit
|
|
518
|
+
client.document.process(
|
|
519
|
+
file_path: './receipt.jpg',
|
|
520
|
+
auto_delete: false,
|
|
521
|
+
boost_mode: false,
|
|
522
|
+
async: false,
|
|
523
|
+
external_id: nil,
|
|
524
|
+
max_pages_to_process: nil,
|
|
525
|
+
tags: nil,
|
|
526
|
+
categories: Veryfi::Api::Document::CATEGORIES
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
# Defaults omitted (recommended — least noise)
|
|
530
|
+
client.document.process(file_path: './receipt.jpg')
|
|
531
|
+
|
|
532
|
+
# Only the non-defaults
|
|
533
|
+
client.document.process(
|
|
534
|
+
file_path: './receipt.jpg',
|
|
535
|
+
auto_delete: true,
|
|
536
|
+
tags: ['expense']
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
# Same call, mixing styles
|
|
540
|
+
client.document.process(
|
|
541
|
+
file_path: './receipt.jpg',
|
|
542
|
+
boost_mode: false, # explicit default — purely for readability
|
|
543
|
+
external_id: '123456789'
|
|
544
|
+
)
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
If you ever need to know the default list of categories at runtime,
|
|
548
|
+
it lives at `Veryfi::Api::Document::CATEGORIES`.
|
|
549
|
+
|
|
550
|
+
## Available APIs
|
|
551
|
+
|
|
552
|
+
The `Veryfi::Client` exposes the full Veryfi API surface through namespaced sub-objects. All sub-objects share the same underlying authenticated `Veryfi::Request`, so a single client instance is enough.
|
|
553
|
+
|
|
554
|
+
```ruby
|
|
555
|
+
client = Veryfi::Client.new(
|
|
556
|
+
client_id: 'your_client_id',
|
|
557
|
+
client_secret: 'your_client_secret',
|
|
558
|
+
username: 'your_username',
|
|
559
|
+
api_key: 'your_api_key'
|
|
560
|
+
)
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Documents
|
|
564
|
+
|
|
565
|
+
```ruby
|
|
566
|
+
client.document.all # GET /partner/documents/
|
|
567
|
+
client.document.get(document_id) # GET /partner/documents/:id
|
|
568
|
+
client.document.process(file_path: 'receipt.jpg') # POST /partner/documents/ (upload)
|
|
569
|
+
client.document.process_url(file_url: 'https://...') # POST /partner/documents/ (url)
|
|
570
|
+
client.document.process_bulk(%w[https://... https://...]) # POST /partner/documents/bulk/
|
|
571
|
+
client.document.update(document_id, notes: 'edited') # PUT /partner/documents/:id
|
|
572
|
+
client.document.delete(document_id) # DELETE /partner/documents/:id
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Tags
|
|
576
|
+
|
|
577
|
+
```ruby
|
|
578
|
+
client.tag.all # GET /partner/tags/
|
|
579
|
+
client.tag.delete(tag_id) # DELETE /partner/tags/:id
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Document Tags
|
|
583
|
+
|
|
584
|
+
```ruby
|
|
585
|
+
client.document_tag.all(document_id) # GET /partner/documents/:id/tags/
|
|
586
|
+
client.document_tag.add(document_id, name: 'priority') # PUT /partner/documents/:id/tags/
|
|
587
|
+
client.document_tag.add_multiple(document_id, %w[a b c]) # POST /partner/documents/:id/tags/
|
|
588
|
+
client.document_tag.replace(document_id, %w[a b c]) # PUT /partner/documents/:id/
|
|
589
|
+
client.document_tag.delete(document_id, tag_id) # DELETE /partner/documents/:id/tags/:tag_id
|
|
590
|
+
client.document_tag.delete_all(document_id) # DELETE /partner/documents/:id/tags/
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### Line Items
|
|
594
|
+
|
|
595
|
+
```ruby
|
|
596
|
+
client.line_item.all(document_id) # GET /partner/documents/:id/line-items/
|
|
597
|
+
client.line_item.get(document_id, line_item_id) # GET /partner/documents/:id/line-items/:line_id
|
|
598
|
+
client.line_item.create(document_id, description: 'Foo') # POST /partner/documents/:id/line-items/
|
|
599
|
+
client.line_item.update(document_id, line_item_id, discount: 0.9) # PUT /partner/documents/:id/line-items/:line_id
|
|
600
|
+
client.line_item.delete(document_id, line_item_id) # DELETE /partner/documents/:id/line-items/:line_id
|
|
601
|
+
client.line_item.delete_all(document_id) # DELETE /partner/documents/:id/line-items
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Tax Lines
|
|
605
|
+
|
|
606
|
+
```ruby
|
|
607
|
+
client.tax_line.all(document_id) # GET /partner/documents/:id/tax-lines
|
|
608
|
+
client.tax_line.get(document_id, tax_line_id) # GET /partner/documents/:id/tax-lines/:tax_id
|
|
609
|
+
client.tax_line.create(document_id, name: 'Sales Tax', rate: 6.25) # POST /partner/documents/:id/tax-lines
|
|
610
|
+
client.tax_line.update(document_id, tax_line_id, rate: 7.0) # PUT /partner/documents/:id/tax-lines/:tax_id
|
|
611
|
+
client.tax_line.delete(document_id, tax_line_id) # DELETE /partner/documents/:id/tax-lines/:tax_id
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### PDF Split (Documents Set)
|
|
615
|
+
|
|
616
|
+
Split a multi-page PDF into multiple processed documents.
|
|
617
|
+
|
|
618
|
+
```ruby
|
|
619
|
+
client.pdf_split.all # GET /partner/documents-set/
|
|
620
|
+
client.pdf_split.get(documents_set_id) # GET /partner/documents-set/:id
|
|
621
|
+
client.pdf_split.process(file_path: 'multi.pdf') # POST /partner/documents-set/ (upload)
|
|
622
|
+
client.pdf_split.process_url(file_url: 'https://...') # POST /partner/documents-set/ (url)
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### Any Document (A-Docs)
|
|
626
|
+
|
|
627
|
+
Process arbitrary document types using a Veryfi blueprint.
|
|
628
|
+
|
|
629
|
+
```ruby
|
|
630
|
+
client.any_document.all # GET /partner/any-documents/
|
|
631
|
+
client.any_document.get(document_id) # GET /partner/any-documents/:id
|
|
632
|
+
client.any_document.process(
|
|
633
|
+
blueprint_name: 'us_w2_2022',
|
|
634
|
+
file_path: 'doc.pdf'
|
|
635
|
+
) # POST /partner/any-documents/ (upload)
|
|
636
|
+
client.any_document.process_url(
|
|
637
|
+
blueprint_name: 'us_w2_2022',
|
|
638
|
+
file_url: 'https://...'
|
|
639
|
+
) # POST /partner/any-documents/ (url)
|
|
640
|
+
client.any_document.process_async(
|
|
641
|
+
blueprint_name: 'us_w2_2022',
|
|
642
|
+
file_path: 'doc.pdf'
|
|
643
|
+
) # POST /partner/any-documents/async (upload)
|
|
644
|
+
client.any_document.process_url_async(
|
|
645
|
+
blueprint_name: 'us_w2_2022',
|
|
646
|
+
file_url: 'https://...'
|
|
647
|
+
) # POST /partner/any-documents/async (url)
|
|
648
|
+
client.any_document.update(document_id, notes: 'edited') # PUT /partner/any-documents/:id
|
|
649
|
+
client.any_document.delete(document_id) # DELETE /partner/any-documents/:id
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Bank Statements
|
|
653
|
+
|
|
654
|
+
```ruby
|
|
655
|
+
client.bank_statement.all # GET /partner/bank-statements/
|
|
656
|
+
client.bank_statement.get(document_id) # GET /partner/bank-statements/:id
|
|
657
|
+
client.bank_statement.process(file_path: 'statement.pdf') # POST /partner/bank-statements/ (upload)
|
|
658
|
+
client.bank_statement.process_url(file_url: 'https://...') # POST /partner/bank-statements/ (url)
|
|
659
|
+
client.bank_statement.process_async(file_path: 'statement.pdf') # POST /partner/bank-statements/async (upload)
|
|
660
|
+
client.bank_statement.process_url_async(file_url: 'https://...') # POST /partner/bank-statements/async (url)
|
|
661
|
+
client.bank_statement.update(document_id, notes: 'edited') # PUT /partner/bank-statements/:id
|
|
662
|
+
client.bank_statement.delete(document_id) # DELETE /partner/bank-statements/:id
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
### Bank Statement Split
|
|
666
|
+
|
|
667
|
+
Split a multi-statement file into individually processed bank statements.
|
|
668
|
+
|
|
669
|
+
```ruby
|
|
670
|
+
client.bank_statement_split.all # GET /partner/bank-statements-set/
|
|
671
|
+
client.bank_statement_split.get(id) # GET /partner/bank-statements-set/:id
|
|
672
|
+
client.bank_statement_split.process(file_path: 'multi.pdf') # POST /partner/bank-statements-set/ (upload)
|
|
673
|
+
client.bank_statement_split.process_url(file_urls: ['https://...']) # POST /partner/bank-statements-set/ (url)
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
### Business Cards
|
|
677
|
+
|
|
678
|
+
```ruby
|
|
679
|
+
client.business_card.all # GET /partner/business-cards/
|
|
680
|
+
client.business_card.get(document_id) # GET /partner/business-cards/:id
|
|
681
|
+
client.business_card.process(file_path: 'card.jpg') # POST /partner/business-cards/ (upload)
|
|
682
|
+
client.business_card.process_url(file_url: 'https://...') # POST /partner/business-cards/ (url)
|
|
683
|
+
client.business_card.update(document_id, company: 'Globex') # PUT /partner/business-cards/:id
|
|
684
|
+
client.business_card.delete(document_id) # DELETE /partner/business-cards/:id
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### Checks
|
|
688
|
+
|
|
689
|
+
```ruby
|
|
690
|
+
client.check.all # GET /partner/checks/
|
|
691
|
+
client.check.get(document_id) # GET /partner/checks/:id
|
|
692
|
+
client.check.process(file_path: 'check.jpg') # POST /partner/checks/ (upload)
|
|
693
|
+
client.check.process_url(file_url: 'https://...') # POST /partner/checks/ (url)
|
|
694
|
+
client.check.process_with_remittance(file_path: 'check.jpg') # POST /partner/check-with-document/ (upload)
|
|
695
|
+
client.check.process_with_remittance_url(file_url: 'https://...') # POST /partner/check-with-document/ (url)
|
|
696
|
+
client.check.process_async(file_path: 'check.jpg') # POST /partner/checks/async (upload)
|
|
697
|
+
client.check.process_url_async(file_url: 'https://...') # POST /partner/checks/async (url)
|
|
698
|
+
client.check.update(document_id, notes: 'edited') # PUT /partner/checks/:id
|
|
699
|
+
client.check.delete(document_id) # DELETE /partner/checks/:id
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### Classify
|
|
703
|
+
|
|
704
|
+
Predict the document type of a file.
|
|
705
|
+
|
|
706
|
+
```ruby
|
|
707
|
+
client.classify.process(
|
|
708
|
+
file_path: 'unknown.jpg',
|
|
709
|
+
document_types: %w[invoice receipt w2]
|
|
710
|
+
) # POST /partner/classify/ (upload)
|
|
711
|
+
client.classify.process_url(
|
|
712
|
+
file_url: 'https://...',
|
|
713
|
+
document_types: %w[invoice receipt w2]
|
|
714
|
+
) # POST /partner/classify/ (url)
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### W-2
|
|
718
|
+
|
|
719
|
+
```ruby
|
|
720
|
+
client.w2.all # GET /partner/w2s/
|
|
721
|
+
client.w2.get(document_id) # GET /partner/w2s/:id
|
|
722
|
+
client.w2.process(file_path: 'w2.pdf') # POST /partner/w2s/ (upload)
|
|
723
|
+
client.w2.process_url(file_url: 'https://...') # POST /partner/w2s/ (url)
|
|
724
|
+
client.w2.update(document_id, notes: 'edited') # PUT /partner/w2s/:id
|
|
725
|
+
client.w2.delete(document_id) # DELETE /partner/w2s/:id
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### W-2 Split
|
|
729
|
+
|
|
730
|
+
Split a file containing multiple W-2 forms into individually processed W-2s.
|
|
731
|
+
|
|
732
|
+
```ruby
|
|
733
|
+
client.w2_split.all # GET /partner/w2s-set/
|
|
734
|
+
client.w2_split.get(w2s_set_id) # GET /partner/w2s-set/:id
|
|
735
|
+
client.w2_split.process(file_path: 'multi_w2.pdf') # POST /partner/w2s-set/ (upload)
|
|
736
|
+
client.w2_split.process_url(file_urls: ['https://...']) # POST /partner/w2s-set/ (url)
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### W-8 BEN-E
|
|
740
|
+
|
|
741
|
+
```ruby
|
|
742
|
+
client.w8.all # GET /partner/w-8ben-e/
|
|
743
|
+
client.w8.get(document_id) # GET /partner/w-8ben-e/:id
|
|
744
|
+
client.w8.process(file_path: 'w8.pdf') # POST /partner/w-8ben-e/ (upload)
|
|
745
|
+
client.w8.process_url(file_url: 'https://...') # POST /partner/w-8ben-e/ (url)
|
|
746
|
+
client.w8.update(document_id, notes: 'edited') # PUT /partner/w-8ben-e/:id
|
|
747
|
+
client.w8.delete(document_id) # DELETE /partner/w-8ben-e/:id
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### W-9
|
|
751
|
+
|
|
752
|
+
```ruby
|
|
753
|
+
client.w9.all # GET /partner/w9s/
|
|
754
|
+
client.w9.get(document_id) # GET /partner/w9s/:id
|
|
755
|
+
client.w9.process(file_path: 'w9.pdf') # POST /partner/w9s/ (upload)
|
|
756
|
+
client.w9.process_url(file_url: 'https://...') # POST /partner/w9s/ (url)
|
|
757
|
+
client.w9.update(document_id, notes: 'edited') # PUT /partner/w9s/:id
|
|
758
|
+
client.w9.delete(document_id) # DELETE /partner/w9s/:id
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### Per-resource tags
|
|
762
|
+
|
|
763
|
+
Every processed-document resource (`any_document`, `bank_statement`, `business_card`, `check`, `w2`, `w8`, `w9`) exposes the same tag-management methods directly on the resource, mirroring the per-document tag endpoints:
|
|
764
|
+
|
|
765
|
+
```ruby
|
|
766
|
+
client.check.tags(check_id) # GET /partner/checks/:id/tags
|
|
767
|
+
client.check.add_tag(check_id, name: 'priority') # PUT /partner/checks/:id/tags (single)
|
|
768
|
+
client.check.add_tags(check_id, %w[priority urgent]) # POST /partner/checks/:id/tags (multiple)
|
|
769
|
+
client.check.delete_tag(check_id, tag_id) # DELETE /partner/checks/:id/tags/:tag_id
|
|
770
|
+
client.check.delete_tags(check_id) # DELETE /partner/checks/:id/tags (all)
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
The same five methods are available on `client.any_document`, `client.bank_statement`, `client.business_card`, `client.w2`, `client.w8`, and `client.w9`.
|
|
774
|
+
|
|
247
775
|
## Need help?
|
|
248
776
|
|
|
249
777
|
If you run into any issue or need help installing or using the library, please contact support@veryfi.com.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
|
|
5
|
+
require "rspec/core/rake_task"
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
7
|
+
|
|
8
|
+
require "rubocop/rake_task"
|
|
9
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
require "yard"
|
|
13
|
+
YARD::Rake::YardocTask.new(:yard)
|
|
14
|
+
rescue LoadError
|
|
15
|
+
# yard is not required to run the test suite — silently skip if missing
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
desc "Run the full quality + test suite"
|
|
19
|
+
task ci: %i[rubocop spec]
|
|
20
|
+
|
|
21
|
+
task default: :ci
|