🚧 Work in Progress - This project is under active development and all endpoints are not implemented.
A TypeScript-based adaptor that bridges the Beckn Protocol with the Open Charge Point Interface (OCPI) standard, enabling seamless integration between Beckn network participants and OCPI-compliant charging station operators.
This repository is organized as a modular monorepo with separate npm packages:
@beckn/ocpi-adaptor-core- Core SDK with interfaces, types, and transformation utilities@beckn/cache-redis- Redis cache store implementation@beckn/log-clickhouse- ClickHouse log store implementation@beckn/server- Express server factory
Each package can be used independently or together. See packages/README.md for details on testing individual packages.
- OCPI 2.2.1 compliant interface
- Beckn Protocol v1.0 and v2.0 flows (switchable via configuration)
- OCPI tariff and connector mapping with computed power profiles
- Beckn v2
discoversupport with spatial filtering - Quote and order normalisation (offer/payment/buyer sanitisation)
- Optional ClickHouse-backed logging with graceful fallback
POST /discover– Beckn v2 discovery flow (returns an on_discover payload)POST /search– Beckn v1 search handler (501when version is set to 2.0)POST /select– Select handler (maps accepted offers & payment methods)POST /init– Init handler (normalises buyer/offers before responding)POST /auto– Smart dispatcher that routes tosearch,select, orinitbased on request contextGET /beckn-logs– Query ClickHouse-backed interaction logs (parameters:transaction_id,message_id,bap_id,protocol,action,stage,status,method,since,limit)GET /health– Simple health check returning200 OK
- Node.js 16+
- Redis 6+
- ClickHouse 23+
- npm or yarn
- OCPI 2.2+ compatible server credentials
- Docker & Docker Compose (for container deployment)
-
Clone the repository:
git clone https://github.com/beckn/beckn-ocpi-adaptor.git cd beckn-ocpi-adaptor -
Install dependencies:
npm install # or yarn installThis will install dependencies for the root project and all packages in the
packages/directory. -
Set up environment variables(optional):
cp .env.example .env # Update the .env file with your configuration
You can set the environment variables in any other method as well. Dotenv has been setup to set the variables if .env file is present.
- Run in developer mode:
npm run dev -- --config ./path/to/config/file.yaml
If config argument is not passed then it will look for default.yaml file in ./config folder. So to use default config file just run:
npm run devThis repository ships with a production-ready Dockerfile and an extended docker-compose.yml inspired by the beckn/sandbox project. The stack brings up the adaptor alongside Redis and ClickHouse with one command.
cp .env.example .envUpdate the values for your deployment. When using Docker Compose, set the cache and ClickHouse hosts to the service names defined in the compose file:
CACHE_HOST=redis
CACHE_PORT=6379
CACHE_TTL_SECONDS=300
CLICKHOUSE_HOST=clickhouse
CLICKHOUSE_PORT=8123You can maintain a second .env (e.g. .env.local) with CACHE_HOST=127.0.0.1 for non-container development and swap files by adjusting the env_file entry in docker-compose.yml.
docker compose up --buildCompose will provision:
app: the Beckn ↔ OCPI adaptor listening on port4000redis: backing cache (data persisted in theredis-datavolume)clickhouse: log store (data persisted in theclickhouse-datavolume)
The compose file injects .env variables and overrides the cache/log hosts so the adaptor can talk to the companion containers immediately.
docker build -t beckn-ocpi-adaptor:latest .
docker run --rm -p 4000:4000 \
--env-file .env \
-e CACHE_HOST=<redis-host> \
-e CACHE_PORT=6379 \
-e CLICKHOUSE_HOST=<clickhouse-host> \
-e CLICKHOUSE_PORT=8123 \
beckn-ocpi-adaptor:latestOverride CACHE_HOST/CLICKHOUSE_HOST with the addresses of your managed Redis or ClickHouse services. To load a non-default config file, append --config /app/config/custom.yaml to the container command (or override command: in the compose file).
All configuration is done through the configuration file. The default configuration file used is config/default.yaml. This can be changed by using the --config argument while running the adaptor. Here's a complete example with all available options in the config file:
# Environment settings
node_env: development # development, production, or test
port: 3000 # Port to run the server on
# OCPI Configuration
ocpi:
url: https://ocpi.example.com/ocpi/cpo/2.2.1 # Base URL for OCPI API
auth_key: your_ocpi_auth_key_here # Authentication key for OCPI API
# Beckn Protocol Configuration
beckn:
version: "1.0" # Beckn protocol version (1.0 or 2.0)
bpp_id: your_bpp_id # Your Beckn Protocol Provider ID
bpp_uri: https://your-bpp-uri.com # Base URI for your BPP
protocol_server_url: https://protocol-server.example.com # Beckn Protocol Server URL
cache:
store: redis # "redis" (default) or "noop"
host: ${CACHE_HOST} # Redis host (e.g. 127.0.0.1 locally, `redis` in Docker)
port: ${CACHE_PORT} # Redis port (typically 6379)
password: ${REDIS_PASSWORD} # Redis password (set in environment)
ttl_seconds: ${CACHE_TTL_SECONDS} # Default TTL for cached OCPI data
clickhouse:
host: ${CLICKHOUSE_HOST} # ClickHouse host (e.g. 127.0.0.1 locally, `clickhouse` in Docker)
port: ${CLICKHOUSE_PORT} # ClickHouse HTTP port
database: default # Database where logs are stored
username: default # ClickHouse username
password: "" # ClickHouse password (blank if not set)
log_table: app_logs # Table used to persist application logs
logging:
store: noop # "clickhouse" (persistent) or "noop" (in-memory no-op; default)
# Application specific configuration
app:
discovery:
default_radius_meters: 5000 # 5km default search radius
standard_session_kwh: 1 # Default session size in kWh
share_location_details: true # Whether to share location details on discovery
initialization:
refresh_ocpi_cache_on_startup: true # Refresh the OCPI cache during startup
use_cache: true # Use the database cache instead of calling OCPI live for discovery data
# Cancellation terms (optional)
cancellation_terms:
- fulfillment_state: confirmed
cancellation_fee:
percentage: 30 # Percentage of total amount to charge for cancellation
defaults:
item_name: 'EV Charger' # Default item name to useocpi.url: Base URL of the OCPI server- Example:
https://ocpi.example.com/ocpi/cpo/2.2.1
- Example:
ocpi.auth_key: Authentication key for OCPI API
-
beckn.version: Target Beckn protocol version"1.0"or"2.0"
-
beckn.bpp_id: Your Beckn Protocol Provider ID- Example:
bpp.example.com
- Example:
-
beckn.bpp_uri: Base URI for your BPP- Example:
https://bpp.example.com
- Example:
-
beckn.protocol_server_url: Beckn Protocol Server URL- Example:
https://protocol.example.com
- Example:
-
cache.store: Selects the cache backend (redisby default,noopto disable persistence). -
cache.host: Redis host (required whencache.storeisredis)- Example:
127.0.0.1(set torediswhen running via docker compose)
- Example:
-
cache.port: Redis port- Example:
6379
- Example:
-
cache.password: Redis password used when authentication is enabled- Example:
${REDIS_PASSWORD}
- Example:
-
cache.ttl_seconds: Default TTL (in seconds) for cached OCPI payloads- Example:
300
- Example:
-
clickhouse.host: ClickHouse server host -
clickhouse.port: ClickHouse HTTP port (default8123) -
clickhouse.database: Target database for log storage -
clickhouse.username: ClickHouse username (defaultdefault) -
clickhouse.password: ClickHouse password -
clickhouse.log_table: Table name for application logs (defaultapp_logs)
logging.store: Selects the log backend (noopby default).clickhouse: requires theclickhouse.*settings above (can also be set via theLOG_STOREenv var).noop: disables persistent logging; ClickHouse settings may be omitted.
app.discovery.default_radius_meters: Default search radius in meters- Example:
5000(5km)
- Example:
app.discovery.standard_session_kwh: Default session size in kWh- Example:
1
- Example:
app.discovery.share_location_details: Whether to share location detailstrueorfalse
app.initialization.refresh_ocpi_cache_on_startup: Refreshes the OCPI cache when the adaptor bootstrueorfalse
app.initialization.use_cache: Whenfalse, discovery data is fetched live from the OCPI server instead of the database cachetrueorfalse
app.defaults.item_name: Default item name- Example:
'EV Charger'
- Example:
You can provide environment variables in the config yaml file using the following format:
${ENV_VARIABLE_NAME}
Start the development server:
npm run dev -- --config ./path/to/config/file.yamlIf config argument is not passed then it will look for default.yaml file in ./config folder. So to use default config file just run:
npm run devBuild for production:
npm run build
npm start -- --config ./path/to/config/file.yamlIf config argument is not passed then it will look for default.yaml file in ./config folder. So to use default config file just run:
npm run build
npm startYou can test each package independently:
# Test all packages
npm run test:packages
# Test individual packages
npm run test:core # Test core package (no external dependencies)
npm run test:cache-redis # Test Redis cache (requires Redis)
npm run test:log-clickhouse # Test ClickHouse log (requires ClickHouse)
npm run test:server # Test Express serverSee packages/README.md for detailed testing instructions.
The repository uses OpenAPI specifications to generate Zod schemas for type validation:
# Generate all Zod types
npm run generate:zod
# Generate specific versions
npm run generate:zod:v1 # Generate Beckn v1 types
npm run generate:zod:v2 # Generate Beckn v2 types
npm run generate:zod:attributes # Generate attribute schemasPackages can be published individually or all at once:
# Publish all packages
npm run publish:all
# Publish individual packages
npm run publish:core
npm run publish:cache-redis
npm run publish:log-clickhouse
npm run publish:serverWe welcome contributions! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Found a bug? Please help us by opening an issue with:
- Clear title and description
- Steps to reproduce
- Expected vs actual behavior
- Environment details
- Logs if applicable
- Update documentation as needed
- Follow the existing code style
- Keep PRs focused on a single feature/fix
- Reference related issues in your PR
This project is licensed under the MIT License - see the LICENSE file for details.