Unofficial CLI and Python client for the Extend virtual card API
Project description
extendvcc
Unofficial CLI and Python client for the Extend virtual card API.
Disclaimer
This is an unofficial, independent client for Extend's private browser API (
api.paywithextend.com). It is not affiliated with, endorsed by, or supported by Extend, Inc. Use at your own risk. Your Extend account may be suspended for running automation against their private API.
Install
pip install extendvcc-cli
# or
pipx install extendvcc-cli
Standalone binary (no Python required): download from GitHub Releases.
Quick Start
# Log in: prompts for email, password, and the emailed OTP. Device is remembered,
# so you won't be asked again on this machine for a while. No setup required.
extendvcc login
# List parent cards
extendvcc accounts
# List virtual cards
extendvcc cards
Enroll a Parent Card
Enrolling a parent card is a three-step lifecycle:
# 1. Register the card (prompts for card number + CVC; triggers an issuer
# verification email). Card details are typed at a prompt, never passed as flags.
extendvcc enroll \
--display-name "My Amex" \
--cardholder-name "Jane Doe" \
--issuer-id iss_xxx \
--expires 2028-12-31 \
--address1 "123 Main St" \
--city "Springfield" \
--province "IL" \
--postal "62701"
# 2. Your card issuer (e.g. Amex) emails you a verification request. Open it and
# approve manually before activation will succeed.
# 3. Pull the card from PENDING to ACTIVE. Re-run if it still reports PENDING.
extendvcc activate <card-id>
Run extendvcc issuers to find the --issuer-id for your card.
Create a One-Time Card
extendvcc create \
--credit-card-id cc_xxx \
--name "My Card" \
--balance-cents 5000 \
--valid-to 2026-12-31
Create a Recurring Card
extendvcc create \
--credit-card-id cc_xxx \
--name "Monthly" \
--balance-cents 10000 \
--period MONTHLY \
--by-month-day 1 \
--terminator NONE
Reveal Credentials
# Show masked card number and CVC on stdout
extendvcc reveal <card-id>
# Write full credentials to a file with 0600 permissions (owner-only)
extendvcc reveal <card-id> --json-path creds.json
--json-path writes the full PAN, CVC, and expiry to a file. Without it, the card number is masked on stdout. --json is a separate global flag that controls JSON output format; it does not write a file.
Dry Run
Destructive commands accept --dry-run to preview the exact operation without
touching the network or mutating anything:
extendvcc create --credit-card-id cc_x --name "Test" --balance-cents 5000 --valid-to 2026-12-31 --dry-run
extendvcc bulk cards.csv --credit-card-id cc_x --dry-run
extendvcc cancel <card-id> --dry-run
extendvcc close <card-id> --dry-run
extendvcc update <card-id> --balance-cents 9000 --dry-run
The would-be request body (or operation descriptor) is printed as JSON to stdout;
the human-readable plan goes to stderr. So extendvcc create ... --dry-run > body.json
captures just the JSON. create/bulk resolve the recipient locally (from --recipient,
else the saved session) and never call the API; the preview is labelled approximate
when the recipient falls back to a placeholder. update --dry-run performs only the
read-only GET needed to show the accurate merged PUT body, with no mutation.
Exit Codes
The CLI uses stable exit codes so scripts and CI can branch on the outcome:
| Code | Name | Meaning |
|---|---|---|
| 0 | OK | Success. |
| 1 | ERROR | Generic failure (library error, or an aborted confirmation). |
| 2 | USAGE | Bad flags or CLI input validation (e.g. missing --valid-to). |
| 3 | AUTH_REQUIRED | Login, OTP, or a saved session is required or failed. |
| 4 | DISABLED | Kill switch tripped (account-risk); run clear-disabled --manual. |
| 5 | API_ERROR | Extend returned an error response. |
Unattended / Automation Use
You can skip this entire section for normal use. extendvcc login prompts for
everything it needs. The variables below only matter when you want to run the CLI with
no human present (a cron job, CI pipeline, or script), where there's nothing to type
into a prompt.
To log in non-interactively, supply the credentials as environment variables. Extend still requires a one-time code (OTP) emailed on login; set the IMAP variables so the CLI can read that code from your inbox automatically. If IMAP retrieval times out, it falls back to a manual prompt.
| Variable | Purpose |
|---|---|
EXTENDVCC_EMAIL |
Extend account email (replaces the email prompt) |
EXTENDVCC_PASSWORD |
Extend account password (replaces the password prompt) |
EXTENDVCC_IMAP_USER |
Inbox address to read the login OTP from |
EXTENDVCC_IMAP_PASSWORD |
IMAP app password for that inbox |
EXTENDVCC_IMAP_HOST |
IMAP server (default: imap.gmail.com) |
Inject these from your secrets manager or CI vault at runtime. Don't commit them to a file.
Advanced overrides
Rarely needed. Change only if the defaults don't fit your setup.
| Variable | Purpose |
|---|---|
EXTENDVCC_STATE_DIR |
Override session/state directory |
EXTENDVCC_LEDGER_PATH |
Override ledger file path |
EXTENDVCC_BRAND_ID |
Override Extend brand ID |
Python API
from extendvcc import list_cards, get_card, create_card, reveal_card
# List all virtual cards
cards = list_cards()
# Get a single card by ID
card = get_card("card_id_here")
# Reveal card credentials (PAN, CVC, expiry)
creds = reveal_card("card_id_here")
See extendvcc.__init__ for the full list of exported functions and models.
Testing
The pytest suite runs entirely offline against fakes. It never touches the network.
Security Notes
- The ledger never stores PAN or CVC data.
revealsaves credentials with0600file permissions.- Session tokens are stored locally with restricted permissions.
- All HTTP uses Chrome TLS fingerprinting via
impit.
License
Project details
Release history Release notifications | RSS feed
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 extendvcc_cli-0.1.2.tar.gz.
File metadata
- Download URL: extendvcc_cli-0.1.2.tar.gz
- Upload date:
- Size: 93.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c0a19848f61da9add4e4dc1b5fdc06f33b8ad8ddbaa9f0883a836be7268f35a
|
|
| MD5 |
76aba591740d919aafe9810936179b60
|
|
| BLAKE2b-256 |
d08806a16f16691238bc4a508c027d5cd784327a877b89ac688c793177cdfaa3
|
Provenance
The following attestation bundles were made for extendvcc_cli-0.1.2.tar.gz:
Publisher:
release.yml on 4LAU/extendvcc
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
extendvcc_cli-0.1.2.tar.gz -
Subject digest:
2c0a19848f61da9add4e4dc1b5fdc06f33b8ad8ddbaa9f0883a836be7268f35a - Sigstore transparency entry: 1832396700
- Sigstore integration time:
-
Permalink:
4LAU/extendvcc@288d82323c200707725badb41c70480de5d188f4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/4LAU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@288d82323c200707725badb41c70480de5d188f4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file extendvcc_cli-0.1.2-py3-none-any.whl.
File metadata
- Download URL: extendvcc_cli-0.1.2-py3-none-any.whl
- Upload date:
- Size: 47.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd59b4eaf1f795ba1267d2a2faa15a83828976a2d6a188ac4f81216364ed9161
|
|
| MD5 |
a37a8d8caf0edd31c44bdf5ad863b9ad
|
|
| BLAKE2b-256 |
5341ee63237e1a45e11ef83b62a69c40f6ca89aeb4536225aa5f3f717db472f9
|
Provenance
The following attestation bundles were made for extendvcc_cli-0.1.2-py3-none-any.whl:
Publisher:
release.yml on 4LAU/extendvcc
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
extendvcc_cli-0.1.2-py3-none-any.whl -
Subject digest:
dd59b4eaf1f795ba1267d2a2faa15a83828976a2d6a188ac4f81216364ed9161 - Sigstore transparency entry: 1832397210
- Sigstore integration time:
-
Permalink:
4LAU/extendvcc@288d82323c200707725badb41c70480de5d188f4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/4LAU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@288d82323c200707725badb41c70480de5d188f4 -
Trigger Event:
push
-
Statement type: