Bank-Slip-Verifier (pip)
Zero-dependency client for the OIIO Service Slip Verify API — verify Thai bank transfer slips with pip, uv, poetry or any Python 3.10+ runtime
English - Thai
Three verification modes, one client — verify that a "paid" slip image or QR payload really moved money in the bank system:
| Mode | Endpoint | Speed |
|---|---|---|
detect_amount(img) |
POST /api/slip |
Slowest — reads the amount from the image with OCR, then verifies it |
verify_amount(img, amount) |
POST /api/slip/:amount |
Faster — you give the expected amount, OCR is skipped |
verify_qr_code(qr_code_data, amount) |
POST /api/slip/:amount/no_slip |
Fastest — QR payload only, no image |
Features
| Ability | Details |
|---|---|
| Three endpoints | OCR amount detection, image + expected amount, and QR-only verification — same typed result for all |
| Static API | from bank_slip_verifier import Client — no construction, Client.verify_amount(...) just works against the hosted deployment |
| Zero dependencies | pure standard library (urllib), no install scripts, no native binaries |
| Typed errors | SlipApiError carries the HTTP status, the documented slug (amount-not-verified, slip-not-found, ...) and the raw envelope, plus SlipTimeoutError and SlipError |
| Timeout-aware | defaults to a 35 s HTTP timeout — verification can take up to 25 s (OCR) |
| npm parity | same endpoints, payloads, error slugs and messages as the npm SDK (@byteindev/bank-slip-verifier) |
Quick Start
Install with any package manager:
pip install bank-slip-verifier
# or
uv add bank-slip-verifier
# or
poetry add bank-slip-verifier
Client is a ready-to-use static wrapper around the hosted deployment — no setup needed:
from bank_slip_verifier import Client
# 1. Verify a QR payload only, no image (fastest):
result = Client.verify_qr_code(qr_code_data="004...", amount=100)
print(result.data.ref) # bank transaction reference
# 2. Verify a slip image against a known amount (recommended — faster):
data = Client.verify_amount(img="data:image/jpeg;base64,...", amount=100).data
print(data.amount == 100) # True — the bank confirmed the transfer
# 3. Unknown amount — let OCR read it from the image (slowest):
detected = Client.detect_amount(img="data:image/jpeg;base64,...").data
print(detected.amount) # amount found by OCR, then verified
Every result has the same shape:
SlipResult(
ok=True,
message="Slip processed successfully.",
from_cache=False, # True when answered from the server cache
data=SlipData(
ref="202602032204376094",
date="2026-03-17T10:00:00.000Z",
amount=100.0,
sender_bank="004",
sender_name="John Doe",
sender_id="xxx-x-xxxxx-x",
receiver_bank="014",
receiver_name="Jane Doe",
receiver_id="xxx-x-xxxxx-x",
),
)
Extra fields come back on rich responses (verified, reference_1/2/3, sender_bank_details, receiver_bank_details).
Bring your own deployment (or configure)
from bank_slip_verifier import create_client
client = create_client() # hosted: https://slip-c.oiio.download
# or
custom = create_client(base_url="https://your-deployment.example.com")
# or configure the static client:
Client.configure(base_url="https://your-deployment.example.com")
result = custom.verify_amount(img="data:image/jpeg;base64,...", amount=100)
Base URL resolution order: base_url option > BANK_SLIP_VERIFIER_BASE_URL
environment variable > hosted deployment:
BANK_SLIP_VERIFIER_BASE_URL=https://staging.example.com python app.py
Timeout
Verification can take up to 25 seconds (OCR endpoint). The API docs require an HTTP
timeout of 30 s or more — this client defaults to 35 s and raises SlipTimeoutError
when a response does not arrive in time. Tighten it only if you know what you are doing:
client = create_client(timeout_ms=60_000) # or lower, but >= 30_000
Terms of Service
The API rejects every request unless TOS, privacy and EULA are accepted. The client sends
{"tos": True, "privacy": True, "eula": True} by default (using the service implies consent).
Override at client level or per call:
create_client(consent={"tos": True, "privacy": False, "eula": True}) # client-level
client.detect_amount(img, consent={"tos": False}) # per-call (wins)
Error handling
All errors extend SlipError. The API's failures arrive as SlipApiError with the HTTP
status, the documented error slug and the raw envelope:
from bank_slip_verifier import Client, SlipApiError, SlipTimeoutError, SlipError
try:
result = Client.verify_amount(img=img, amount=100)
except SlipApiError as err:
print(err.status, err.slug, err.message)
# 422 'amount-not-verified' '[amount-not-verified] Amount not verified'
if err.slug == "amount-not-verified":
# show the customer the expected amount again — the slip does not match
...
except SlipTimeoutError:
# verification took longer than timeout_ms — retry later
...
| HTTP | slug | Cause |
|---|---|---|
| 400 | bad-request |
malformed body / missing field |
| 400 | terms-not-accepted |
TOS/Privacy/EULA not accepted |
| 400 | invalid-image |
base64 image is invalid |
| 422 | qr-not-found |
no QR found in the image |
| 422 | invalid-qr |
QR format invalid |
| 422 | amount-not-found |
OCR could not read the amount |
| 422 | amount-not-verified |
amount read, but did not match the bank record |
| 422 | invalid-slip-data |
slip data incomplete |
| 404 | slip-not-found |
slip not found in the bank system |
SlipApiError.slug is one of these values (SLIP_ERROR_SLUGS and is_slip_error_slug
are exported for runtime checks).
Live smoke tests
The package ships live smoke tests against the real deployment (skipped by default):
LIVE=1 pytest
API
| Export | Description |
|---|---|
Client |
static wrapper around a shared instance (hosted deployment by default) |
create_client(**options) |
new SlipClient connected to hosted or custom base_url |
SlipClient |
the client class; detect_amount, verify_amount, verify_qr_code |
DEFAULT_BASE_URL |
https://slip-c.oiio.download |
ENV_BASE_URL |
BANK_SLIP_VERIFIER_BASE_URL — env-var fallback for the base URL |
SlipError / SlipApiError / SlipTimeoutError |
typed errors |
SLIP_ERROR_SLUGS, is_slip_error_slug |
error slug constants + guard |
SlipData / SlipResult |
result types |
__version__ |
package version |
Credits
Powered by the OIIO Service Slip Verify API.
License
MIT © ByteInDev
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bank_slip_verifier-1.0.0.tar.gz.
File metadata
- Download URL: bank_slip_verifier-1.0.0.tar.gz
- Upload date:
- Size: 17.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd7ca6b274592895d8f9d2ae054bbbf54a26a5756590e69d9705919d3243fb06
|
|
| MD5 |
560025e815053261fdb72391581fc080
|
|
| BLAKE2b-256 |
232abbb70e4465f8c2e62f6749068f820a8c8e8be778f9a5256237bb4917124b
|
File details
Details for the file bank_slip_verifier-1.0.0-py3-none-any.whl.
File metadata
- Download URL: bank_slip_verifier-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd70cda48b69b51465533f2340b0c61068170d6c17457de082a95f0f35ecec08
|
|
| MD5 |
3699871f5ee27aee9aeeb558512a68e7
|
|
| BLAKE2b-256 |
3154693563aaa5d5ca5e2025d3823eb1a3bea9c00c317191db288d7b152b93df
|