📖 Read this in Spanish / Leer en Español
An open source Node.js/Express API for generating CoDi (Cobro Digital) payment requests via QR codes and Push notifications, integrating with Banxico (Bank of Mexico).
CoDi API is a production-ready REST API that enables Mexican businesses to generate digital payment requests through Mexico's Central Bank (Banxico) CoDi system. The API supports two payment methods:
- QR Code Payments: Generate dynamic QR codes for customers to scan and pay
- Push Notifications: Send payment requests directly to customers' mobile banking apps via phone number
- ✅ Digital Signature Authentication: RSA certificate-based authentication with Banxico
- ✅ Dual Environment Support: Separate Beta and Production configurations
- ✅ Fallback Architecture: Multiple endpoint support for high availability
- ✅ API Key Management: Secure API key generation and validation via Supabase
- ✅ Request/Response Logging: Complete audit trail of all transactions
- ✅ Webhook Support: Receive real-time payment status updates
- ✅ Security Hardened: Helmet, CORS, rate limiting, request sanitization
- ✅ Interactive API Documentation: Swagger/OpenAPI documentation
- ✅ Comprehensive Testing: Jest test suite with coverage reporting
- Prerequisites
- Installation
- Configuration
- Database Setup
- API Endpoints
- Authentication
- Digital Certificates
- Development
- Testing
- Deployment
- Security
- Contributing
- License
Before you begin, ensure you have the following:
- Node.js 18.x or higher
- npm 9.x or higher
- Supabase Account: For database and API key management (supabase.com)
- Banxico Developer Account: Required for CoDi integration
- Apply at: Banxico CoDi Developer Portal
- You will receive:
- Digital certificates
- API endpoints for Beta and Production environments
- Banxico public certificates
- For both testing and production environments
- PM2: For production process management
- Git: For version control
- PostgreSQL client: For database management (Supabase provides a PostgreSQL database)
- Clone the repository
git clone https://github.com/portfedh/codi-api.git
cd codi-api- Install dependencies
npm install- Set up environment variables
cp .env.example .envEdit .env with your configuration (see Configuration section).
- Set up the database
Follow the Database Setup instructions to create the required tables in Supabase.
- Generate your first API key (optional for testing)
node controllers/utils/generateApiKey.jsThis will generate a 128-character hexadecimal API key that you can add to the api_keys table in Supabase.
The .env file contains all configuration variables. See .env.example for a complete template.
PORT=3131
NODE_ENV=development # or productionDefine allowed origins for your API:
CORS_ALLOWED_ORIGINS=https://yourdomain.com,http://localhost:3000
CORS_BANXICO_BETA=http://banxico-beta-ip
CORS_BANXICO_PROD=http://banxico-prod-ipSUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_keyYou will receive these URLs from Banxico when you register as a developer:
# QR Payment Endpoints
SITIO_CODI_QR_DEV_1=https://banxico-dev-qr-endpoint-1.com
SITIO_CODI_QR_DEV_2=https://banxico-dev-qr-endpoint-2.com
SITIO_CODI_QR_PROD_1=https://banxico-prod-qr-endpoint-1.com
SITIO_CODI_QR_PROD_2=https://banxico-prod-qr-endpoint-2.com
# Push Payment Endpoints
SITIO_CODI_PUSH_DEV_1=https://banxico-dev-push-endpoint-1.com
SITIO_CODI_PUSH_DEV_2=https://banxico-dev-push-endpoint-2.com
# ... and so onSee Digital Certificates section for detailed instructions.
This API uses Supabase (PostgreSQL) for data persistence.
- Sign up at supabase.com
- Create a new project
- Note your project URL and API keys
The complete database schema is available in /database/schema.sql. Create the following tables:
Core Tables:
customers: Customer information and bank detailsapi_keys: API key management with Banxico integrationfolios_codi: CoDi payment folio trackingrequests: Incoming request loggingresponses: Outgoing response logging
Visual Schema:
See /database/database_schema.png for a visual representation of table relationships.
-- 1. Insert a customer
INSERT INTO customers (name, email, phone, environment, bank_name, bank_account)
VALUES ('Test Customer', '[email protected]', '5551234567', 'development', 'Test Bank', '1234567890');
-- 2. Insert an API key for this customer
INSERT INTO api_keys (
customer_id,
api_key,
banxico_api_key,
environment,
callback_url,
active
)
VALUES (
(SELECT id FROM customers WHERE email = '[email protected]'),
'your_generated_128_char_api_key_here',
'your_banxico_api_key_here',
'development',
'https://your-webhook-url.com/callback',
true
);- Development:
http://localhost:3131 - Production:
https://your-domain.com
All endpoints (except /health) require an API key in the header:
x-api-key: your_128_character_api_keyGET /v2/healthReturns API health status. No authentication required.
Response:
{
"status": "healthy",
"timestamp": "2025-10-06T12:00:00.000Z"
}POST /v2/codi/qrCreates a CoDi payment request and returns a QR code.
Request Body:
{
"monto": "100.50",
"concepto": "Payment for services",
"referencia": "INV-12345"
}Response:
{
"success": true,
"qrCode": "data:image/png;base64,...",
"folioCoDi": "ABC123DEF456",
"mensaje": "QR code generated successfully"
}POST /v2/codi/pushSends a payment request directly to a customer's mobile banking app.
Request Body:
{
"monto": "100.50",
"concepto": "Payment for services",
"referencia": "INV-12345",
"telefonoCliente": "5551234567"
}Response:
{
"success": true,
"folioCoDi": "ABC123DEF456",
"mensaje": "Push notification sent successfully"
}POST /v2/codi/consultaCheck the status of a payment request.
Request Body:
{
"folioCoDi": "ABC123DEF456"
}Response:
{
"success": true,
"status": "paid",
"monto": "100.50",
"fechaPago": "2025-10-06T12:30:00.000Z"
}POST /v2/resultadoOperacionesReceives payment status updates from Banxico. This endpoint is called by Banxico when a payment is completed.
Webhook Payload (sent by Banxico):
{
"folioCoDi": "ABC123DEF456",
"resultado": "exitoso",
"monto": "100.50",
"timestamp": "2025-10-06T12:30:00.000Z"
}Interactive API documentation is available via Swagger UI:
http://localhost:3131/api-docs
The API uses two-layer authentication:
- Your API Key: Generated by you, used by your clients
- Banxico API Key: Provided by Banxico, stored in the database
All requests to/from Banxico are signed with RSA digital certificates for security:
- Outgoing requests are signed with your private key
- Incoming webhooks are verified using Banxico's public certificate
- Certificate serial numbers are validated
You need 4 sets of certificates from Banxico:
-
Developer Beta Environment
- Private key (
.cvefile) - Public certificate (
.crtfile) - Login certificate serial number
- Operation certificate serial number
- Private key (
-
Developer Production Environment
- Same as above, but for production
-
Banxico Beta Public Certificate
- For verifying Banxico signatures in Beta
-
Banxico Production Public Certificate
- For verifying Banxico signatures in Production
Certificate files must be formatted correctly for use in .env:
Convert certificate files to environment variable format:
# For private keys (.cve files)
awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' your_private_key.cve
# For public certificates (.crt files)
awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' your_certificate.crtThis converts newlines to \n characters so the certificate can be stored as a single-line environment variable.
Add to .env:
# Example for Developer Beta Private Key
PRIVATE_KEY_DEV="-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIB...(your key here)...\n-----END RSA PRIVATE KEY-----\n"
PRIVATE_KEY_PASSPHRASE_DEV="your_passphrase"
# Example for Developer Beta Public Certificate
PUBLIC_KEY_DEV="-----BEGIN CERTIFICATE-----\nMIIDXTC...(your cert here)...\n-----END CERTIFICATE-----"
# Certificate Serial Numbers (provided by Banxico)
CRT_LOG_IN_DEV="1234567890"
CRT_OPER_DEV="0987654321"- Never commit certificates to Git: The
.gitignorefile excludes.env - Store production certificates securely (use environment variables in production)
- Rotate certificates before expiration
- Use separate certificates for Beta and Production
npm run devThis uses nodemon to automatically restart the server on file changes.
npm startOr use PM2 for production process management:
pm2 start index.js --name codi-api
pm2 logs codi-apicodi-api/
├── config/ # Configuration files
│ ├── cors.js # CORS configuration
│ ├── institutions.js # Financial institution codes
│ ├── supabase.js # Supabase client setup
│ └── swagger.js # Swagger/OpenAPI config
├── controllers/ # Route controllers
│ ├── consulta.js # Payment status queries
│ ├── health.js # Health check endpoint
│ ├── resultadoOperaciones.js # Webhook handler
│ ├── sendPushPayment.js # Push payment logic
│ ├── sendQrPayment.js # QR payment logic
│ └── utils/ # Utility functions (35+ helpers)
├── database/ # Database schema and diagrams
├── middleware/ # Express middleware
│ └── sanitizeRequest.js # Request sanitization
├── routes/ # Route definitions
│ └── home.js # Main router
├── tests/ # Jest test suite
├── validators/ # Request validation schemas
├── .env.example # Environment variables template
├── index.js # Application entry point
└── package.json # Project dependencies
The API includes 35+ utility functions for:
- Certificate handling and signature verification
- Banxico credential management
- Request/response logging to Supabase
- Data validation and formatting
- Fallback request mechanisms
- QR code generation
- API key management
npm testThis runs the Jest test suite with coverage reporting.
Tests cover:
- All utility functions
- Validation rules
- Certificate verification
- Digital signature generation
- Request formatting
- Error handling
Coverage reports are generated in /coverage directory.
Health Check:
curl http://localhost:3131/v2/healthQR Payment Request:
curl -X POST http://localhost:3131/v2/codi/qr \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{
"monto": "100.50",
"concepto": "Test payment",
"referencia": "TEST-001"
}'- Set
NODE_ENV=productionin.env - Configure production Banxico endpoints
- Use production digital certificates
- Set up production Supabase database
- Configure CORS for production domains
- Enable HTTPS/SSL
- Set up process manager (PM2 recommended)
- Configure log rotation
- Set up monitoring and alerts
- Review rate limiting settings
- Test webhook endpoint accessibility
# Install PM2
npm install -g pm2
# Start the API
pm2 start index.js --name codi-api
# Save PM2 configuration
pm2 save
# Set up PM2 to start on system boot
pm2 startupFor production, use your hosting provider's environment variable management instead of .env files:
- Vercel: Use Environment Variables in project settings
- Heroku: Use
heroku config:set - AWS/GCP/Azure: Use their respective secret management services
- Docker: Use Docker secrets or environment files
- Helmet: Security headers (XSS protection, content security policy, etc.)
- CORS: Strict origin validation
- Rate Limiting: 200 requests per 15 minutes per IP
- Request Sanitization: SQL injection and XSS prevention
- API Key Validation: 128-character hexadecimal keys
- Digital Signatures: RSA certificate-based authentication
- Hidden File Blocking: Prevents access to
.git,.env, etc. - Request Logging: Complete audit trail in Supabase
- Never expose your
.envfile - Rotate API keys regularly
- Monitor rate limit violations
- Keep dependencies updated:
npm audit fix - Use HTTPS in production
- Validate webhook signatures from Banxico
- Review access logs regularly:
pm2 logs codi-api - Set up alerts for suspicious activity
If you discover a security vulnerability, please email the maintainer directly rather than opening a public issue.
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Make your changes
- Add tests for new functionality
- Run tests:
npm test - Commit your changes:
git commit -m "Add: your feature description" - Push to your fork:
git push origin feature/your-feature-name - Open a Pull Request
- Use 2 spaces for indentation
- Follow existing code patterns
- Add JSDoc comments for functions
- Write descriptive commit messages
- Ensure all tests pass before submitting PR
- Enhanced error handling
- Performance optimizations
- Documentation improvements
- Additional test coverage
- Security enhancements
- Internationalization (i18n)
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- ✅ Commercial use allowed
- ✅ Modification allowed
- ✅ Distribution allowed
- ✅ Patent grant included
- ✅ Private use allowed
⚠️ Must include copyright notice and license⚠️ Must state significant changes- ❌ No liability or warranty
- API Documentation:
/api-docsendpoint (Swagger UI) - Database Schema:
/database/schema.sql - Schema Diagram:
/database/database_schema.png - Environment Setup:
.env.example
- Banxico CoDi Documentation: https://www.banxico.org.mx/codi/
- Supabase Documentation: https://supabase.com/docs
- Express.js Documentation: https://expressjs.com/
- Issues: GitHub Issues
- Discussions: GitHub Discussions
If you find CoDi API valuable for your business or projects, please consider sponsoring its development. Your support helps:
- 🚀 Maintain and improve the codebase
- 📚 Create better documentation and tutorials
- 🔒 Enhance security features
- ✨ Add new features and integrations
- 🐛 Fix bugs and respond to issues faster
Every contribution, no matter the size, makes a difference! 💖
- Banxico (Bank of Mexico) for the CoDi payment system
- Supabase for the database and authentication platform
- All contributors and users of this project
Future enhancements under consideration:
- Webhook retry mechanism with exponential backoff
- Enhanced reporting and analytics
- SDK libraries (JavaScript, Python, PHP)
Created by Pablo Cruz Lemini
For questions or feedback, please open an issue on GitHub.