Bitcart runs a merchant payment stack as daemons, an API and a worker
Bitcart is a free and open-source self-hosted payment processor for BTC, LTC, BCH, XMR, ETH, TRX, USDT and more
At a glance
- What is it?
- Bitcart is a self-hosted, MIT licensed payment processor for BTC, LTC, BCH, XMR, ETH, TRX and USDT, built in Python around FastAPI, per-coin daemons and a separate task worker. The code is current and the architecture is clear, but the operational surface is wider than a single service implies.
- Who is it for?
- Bitcart fits operators who want their own payment stack for several coins and can afford to run three process types plus per-coin daemons, and it fits teams that want the checkout logic in a scriptable language rather than in application code. It does not fit a merchant who wants a single install, a hosted dashboard, or a guaranteed set of supported coins.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- bitcart/bitcart1,005 ★ · +10
| Repository | 2026-10-21 | 2026-11-07 |
|---|---|---|
| bitcart/bitcart | 995 | 1k |
10 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
One payment problem, split across five linked repositories
Bitcart targets a narrow job: accepting cryptocurrency payments for merchants without handing funds to a third party processor. The project description lists BTC, LTC, BCH, XMR, ETH, TRX and USDT, and the topic tags name bitcoin-payment-gateway, ethereum-payment-gateway, monero and lightning-adjacent tooling. The primary language is Python, and the central repository is described as holding the core daemons and the Merchants API.
The interesting part is that the central repository is deliberately not the whole product. The README calls this the central repository of an ecosystem and lists sibling projects: bitcart-admin for the admin panel, bitcart-store for a ready-made storefront, bitcart-docker for packaging, bitcart-sdk as a Python library for coin connections, and bitccl, a scripting language for checkout flow automation. Documentation lives in a separate bitcart-docs repository.
That split has a practical consequence for an evaluator. Feature requests are explicitly routed to this central repository, as requests for the ecosystem as a whole, and a deployment decision spans at least two repositories, because Docker packaging is the stated base for all deployment methods. Anyone assessing Bitcart is assessing a family of projects with independent release cycles, not a single package.
The dependency groups tell you what a running deployment actually loads
The pyproject.toml at the root of the core repository is the most informative file for judging the shape of the system. The project is named bitcart-api, its description is Bitcart Merchants API, and it requires Python 3.12 or newer. Two dependencies sit in the base set, python-decouple for configuration and rust-just for task running, which matches the justfile sitting next to it.
Everything else is grouped. The web group carries the actual service stack: fastapi, starlette, uvicorn, sqlalchemy with asyncio support, alembic, asyncpg, redis, taskiq and taskiq-redis for background work, pydantic and pydantic-settings, jinja2, paramiko, fido2 for hardware key support, pyotp for one-time passwords, apprise for notifications, prometheus-client, sentry-sdk, structlog, and a bitcart entry requiring at least 1.18.0.0. A separate otel group pins the OpenTelemetry packages to 0.65b0, and a production group adds gunicorn. Lint and test groups carry ruff, mypy, deptry, pytest, fakeredis and httpx.
Reading these groups as a deployment plan, a production install pulls in roughly forty runtime libraries, a message broker, a database driver and a task queue. The database layer is explicitly asynchronous, which is a reasonable choice for a service that spends its life waiting on blockchain backends, but it also means a single PostgreSQL instance is part of the minimum topology.
Three process types have to be running for a checkout to work
The justfile in the repository root defines the run targets, and it makes the required process topology obvious. The API runs under uvicorn with websockets enabled and a one second graceful shutdown window, in development with reload enabled. A separate worker process runs its own Python entry point. Production swaps uvicorn for gunicorn against a checked-in gunicorn.conf.py, and a production-up recipe chains the database migration in front of it.
For a first local run, the API service is the piece to start first, because the worker and the daemons both talk to services that the API brings up:
uvicorn main:app --ws websockets-sansio --timeout-graceful-shutdown 1 --reloadNext, start the background worker in a second terminal, since it is the component that picks up queued work such as invoice monitoring and notifications:
python3 worker.pyCoin daemons are per-coin processes started from the same justfile, with the coin name passed in:
python3 daemons/{{ coin }}.pyThe daemons directory at the repository root holds these per-coin entry points, and a base daemon dependency on aiohttp is declared for the daemon group. The base group is shared, with coin-specific groups layered on top, which is how one codebase ends up serving Monero, Ethereum and Bitcoin at the same time. You should expect to run one daemon per coin you intend to accept, and the README does not document a way to run all of them from a single process.
Schema changes are alembic migrations, and a rollback is one downgrade step
Bitcart keeps its database under alembic, with an alembic.ini at the repository root and a migrations directory beside it. The justfile exposes the full migration lifecycle, which is worth reading because it shows how much of the operational burden the project hands to the operator.
To move a fresh database to the current schema, the repository gives you:
alembic upgrade headTo step back one revision, it gives you:
alembic downgrade -1Creating a new migration during development is a one-liner as well:
alembic revision --autogenerate -m "{{ MESSAGE }}"The production-up recipe chains `db-migrate prod-api`, so a deployment applies pending migrations before the new API process starts serving. That ordering is the right one for a payment service where an invoice table half-migrated underneath a live worker is the failure you least want. The dependency on asyncpg and the Alembic configuration are visible in the repository, but the README does not document how the database connection string is supplied at runtime, and the configuration is handled through python-decouple rather than a documented environment variable list.
Checkout logic lives in bitccl, not in your application code
The most distinctive choice in the ecosystem is bitccl, described in the README as the BitCCL scripting language for checkout flow automation. Instead of asking a merchant to write server code that talks to the payment API, checkout behaviour is expressed in a dedicated language with its own repository.
For a merchant, that separation is the appeal. Discount rules, invoice creation, payment verification and any branching on coin behaviour can sit in a script that the platform interprets, and changes to that script do not require redeploying the application. It also means the payment logic is inspectable as data rather than buried in a codebase.
The cost is a second language to learn and a second thing to debug. Nothing in the core repository README describes the bitccl syntax, its error model, or how a script is versioned and rolled back. The documentation repository is the only pointer given, and the project keeps its documentation off the core repository entirely. If your team already has a well-tested checkout implementation, moving it into bitccl is a rewrite rather than an import, and the README gives no indication of an import path.
The real failure modes live in uptime, not in the cryptography
A self-hosted payment processor fails in operational ways that a hosted one absorbs for you. The most obvious is daemon liveness: if the daemon for a given coin stops, invoices for that coin stop advancing, and the operator sees a checkout that appears to hang rather than an error. The worker is the second point of exposure, since invoice polling and notification dispatch both sit behind the taskiq and taskiq-redis pair and a stopped worker means queued work simply accumulates.
The third is the key material. FIDO2 support and paramiko are both in the web dependency group, and a node holding spending keys for a merchant wallet is a target. Nothing in the core README describes key generation, encryption at rest, or rotation, so those details have to be confirmed in the documentation and in the bitcart-sdk repository before funds are involved.
A fourth limit is currency breadth versus certainty. The project description says BTC, LTC, BCH, XMR, ETH, TRX and USDT and more, and the topic tags include binance-smart-chain, so the supported set moves. The tag set also includes electrum, hinting at a light client path for Bitcoin, but the core repository's daemon directories are what determine what is actually implementable today. The README does not document which coins are fully supported for invoice lifecycle, so the per-coin daemon directories are the file to check before committing to a currency.
The repository layout makes the upgrade surface wider than one release
The root of the core repository carries more than application code. Alongside api, daemons, modules, migrations, tests and static, there is worker.py, main.py, gunicorn.conf.py, alembic.ini, a justfile, a uv.lock, a CHANGELOG.md, a SECURITY.md, a CODING_STANDARDS.md, a pre-commit-config.yaml and a .github directory. There is also a context7.json, a file whose purpose is not explained in the README.
The development workflow is unusually well specified for an open source project of this size, and that is a genuine strength. Linting runs through ruff with a separate check-only mode, type checking covers api, tests, main.py and worker.py through mypy, dependency checking uses deptry, and the whole set is bundled into a ci-lint recipe. The full CI recipe chains linting with the test suite, and functional tests are a separate target. The justfile interpolates recipe arguments; the following is the equivalent command without optional arguments, after setting up the test dependencies:
BTC_LIGHTNING=true pytest tests/functional/ --cov-append -n 0The functional suite is explicitly gated on BTC_LIGHTNING being true, which tells you Lightning path coverage is opt-in rather than default. On the maintenance side, the repository is not archived and the last push was on 2026-10-19, one day before this review, so the code is current. The release trail is thinner than the commit trail though: the three most recent tagged releases are 0.10.2.0 on 2026-02-19, 0.10.2.1 on 2026-02-25 and 0.10.3.0 on 2026-03-05, while the root pyproject.toml still declares version 1.0.0 for bitcart-api. That mismatch between the package version and the release tags is a detail to confirm before you pin a version in a deployment manifest.
Editorial conclusion
Bitcart fits operators who want their own payment stack for several coins and can afford to run three process types plus per-coin daemons, and it fits teams that want the checkout logic in a scriptable language rather than in application code. It does not fit a merchant who wants a single install, a hosted dashboard, or a guaranteed set of supported coins. Before adopting it, check that the coin you need is covered by a daemon in the daemons directory, read the deployment guidance for the Docker packaging repository, and confirm you can keep the API, the worker and the daemons under supervision at the same time.
Frequently asked questions
What is Bitcart and which coins does it support?
Bitcart is a free and open-source self-hosted payment processor written in Python, described by the project as a platform for merchants, users and developers. Its project description names BTC, LTC, BCH, XMR, ETH, TRX and USDT among the coins it targets, with a per-coin daemon for each.
How do I run Bitcart locally for development?
The repository's justfile defines the run targets: `uvicorn main:app --ws websockets-sansio --timeout-graceful-shutdown 1 --reload` for the API and `python3 worker.py` for the background worker, with coin daemons started through `python3 daemons/{{ coin }}.py`. Deployment in general is handled by the bitcart-docker repository, which the README calls the base for all deployment methods.
Does Bitcart need a database, and how are schema changes handled?
Yes. The repository ships an alembic.ini and a migrations directory, and sqlalchemy with asyncpg is part of the web dependency group. Migrations are applied with `alembic upgrade head` and can be stepped back with `alembic downgrade -1`.
What licence is Bitcart released under?
The project is released under the MIT licence, with a LICENSE file at the root of the repository. Bitcart is not archived, and the last push was on 2026-10-19.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bitcart-bitcart)Star history chart for your README
[](https://hysenlabs.com/projects/bitcart-bitcart)Was this useful?