API v1

API Reference

Complete reference for all ExportReady-Battery API endpoints. All endpoints use JSON for request and response bodies.

Base URL

https://api.exportready.com/api/v1

All endpoints are relative to this base URL. For local development, use http://localhost:8080/api/v1

Authentication

Protected endpoints require a Bearer token in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Access tokens expire after 15 minutes. Use the refresh token to obtain a new access token.

Authentication

User registration, login, and password management endpoints.

POST/auth/register

Register a new tenant/company account.

Request Body

{
  "company_name": "Acme Batteries",
  "email": "admin@acme.com",
  "password": "SecurePass123!"
}

Response

{
  "message": "Registration successful",
  "tenant_id": "550e8400-e29b-41d4-a716-446655440000"
}
POST/auth/login

Authenticate and receive access & refresh tokens.

Request Body

{
  "email": "admin@acme.com",
  "password": "SecurePass123!"
}

Response

{
  "token": "eyJhbGciOiJIUzI1NiI...",
  "refresh_token": "eyJhbGciOiJIUzI1NiI...",
  "tenant_id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "admin@acme.com",
  "company_name": "Acme Batteries",
  "expires_in": 900
}
POST/auth/refresh

Exchange a refresh token for a new access token.

Request Body

{
  "refresh_token": "eyJhbGciOiJIUzI1NiI..."
}

Response

{
  "token": "eyJhbGciOiJIUzI1NiI...",
  "expires_in": 900
}
POST/auth/forgot-password

Initiate password reset by sending a reset email.

Request Body

{
  "email": "admin@acme.com"
}

Response

{
  "message": "Password reset email sent"
}
POST/auth/reset-password

Complete password reset with token from email.

Request Body

{
  "token": "reset_token_from_email",
  "new_password": "NewSecurePass456!"
}

Response

{
  "message": "Password reset successful"
}
GET/auth/me๐Ÿ” Auth Required

Get the current authenticated user's profile.

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "company_name": "Acme Batteries",
  "email": "admin@acme.com",
  "address": "Industrial Area, Delhi",
  "epr_registration_number": "B-29016/2024-25/CPCB",
  "bis_r_number": "R-41001234",
  "created_at": "2026-01-15T10:00:00Z"
}
PUT/auth/profile๐Ÿ” Auth Required

Update the current user's profile and compliance fields.

Request Body

{
  "company_name": "Acme Batteries Inc.",
  "address": "Updated Address, Mumbai",
  "support_email": "support@acme.com",
  "website": "https://acme.com",
  "epr_registration_number": "B-29016/2024-25/CPCB",
  "bis_r_number": "R-41001234",
  "iec_code": "0504012345"
}

Response

{
  "message": "Profile updated successfully"
}

Batches

Create, manage, and export battery batches.

POST/batches๐Ÿ” Auth Required

Create a new battery batch with specifications.

Request Body

{
  "batch_name": "Q1-2026-Production",
  "market_region": "INDIA",
  "specs": {
    "chemistry": "Li-ion NMC",
    "voltage": "48V",
    "capacity": "100Ah",
    "manufacturer": "Acme Batteries",
    "weight": "45kg",
    "country_of_origin": "India"
  },
  "pli_compliant": true,
  "domestic_value_add": 65.5,
  "cell_source": "DOMESTIC"
}

Response

{
  "id": "batch-uuid-here",
  "batch_name": "Q1-2026-Production",
  "created_at": "2026-01-15T10:00:00Z"
}
GET/batches๐Ÿ” Auth Required

List all batches for the authenticated tenant with pagination.

Response

{
  "batches": [
    {
      "id": "batch-uuid-1",
      "batch_name": "Q1-2026-Production",
      "total_passports": 500,
      "market_region": "INDIA",
      "created_at": "2026-01-15T10:00:00Z"
    }
  ],
  "total": 10,
  "page": 1,
  "per_page": 20
}
GET/batches/{id}๐Ÿ” Auth Required

Get detailed information about a specific batch.

Response

{
  "id": "batch-uuid-here",
  "batch_name": "Q1-2026-Production",
  "market_region": "INDIA",
  "specs": { ... },
  "pli_compliant": true,
  "domestic_value_add": 65.5,
  "total_passports": 500,
  "created_at": "2026-01-15T10:00:00Z"
}
POST/batches/{id}/upload๐Ÿ” Auth Required

Upload a CSV file with serial numbers to generate passports.

Request Body

Content-Type: multipart/form-data

file: [CSV file with serial_number,manufacture_date columns]

Response

{
  "message": "Successfully created 500 passports",
  "created": 500,
  "errors": []
}
GET/batches/{id}/download๐Ÿ” Auth Required

Download all QR codes for the batch as a ZIP file.

Response

Content-Type: application/zip
Content-Disposition: attachment; filename="batch-qrcodes.zip"

[Binary ZIP file containing PNG QR codes]
GET/batches/{id}/export๐Ÿ” Auth Required

Export all passports in the batch to a CSV file.

Response

Content-Type: text/csv

uuid,serial_number,manufacture_date,status,qr_url
uuid-1,BAT-001,2026-01-15,ACTIVE,https://example.com/p/uuid-1
GET/batches/{id}/passports๐Ÿ” Auth Required

List all passports in a batch with pagination.

Response

{
  "passports": [
    {
      "uuid": "passport-uuid",
      "serial_number": "BAT-001",
      "manufacture_date": "2026-01-15",
      "status": "ACTIVE"
    }
  ],
  "total": 500,
  "page": 1
}

Passports

Public passport data and scan tracking.

GET/p/{uuid}

Get public passport data. No authentication required.

Response

{
  "uuid": "passport-uuid",
  "serial_number": "BAT-2026-001",
  "manufacture_date": "2026-01-15",
  "status": "ACTIVE",
  "batch": {
    "batch_name": "Q1-2026-Production",
    "market_region": "INDIA",
    "specs": { ... },
    "pli_compliant": true,
    "domestic_value_add": 65.5
  },
  "tenant": {
    "company_name": "Acme Batteries",
    "address": "Industrial Area, Delhi",
    "epr_registration_number": "B-29016/2024-25/CPCB"
  }
}
POST/scan

Record a scan event for a passport. Called automatically when QR is scanned.

Request Body

{
  "passport_id": "passport-uuid"
}

Response

{
  "message": "Scan recorded"
}
GET/scan/feed๐Ÿ” Auth Required

Get real-time scan feed for the authenticated tenant.

Response

{
  "scans": [
    {
      "id": "scan-uuid",
      "passport_id": "passport-uuid",
      "serial_number": "BAT-001",
      "city": "Mumbai",
      "country": "India",
      "device_type": "Mobile",
      "scanned_at": "2026-01-15T14:30:00Z"
    }
  ]
}

Billing

Quota management and Razorpay payment integration.

GET/billing/packages

Get available quota packages for purchase.

Response

{
  "packages": [
    {
      "id": "starter",
      "name": "Starter",
      "quota": 100,
      "price": 999,
      "currency": "INR"
    },
    {
      "id": "professional",
      "name": "Professional",
      "quota": 500,
      "price": 3999,
      "currency": "INR"
    }
  ]
}
GET/billing/quota๐Ÿ” Auth Required

Get current quota balance for the authenticated tenant.

Response

{
  "quota_balance": 450,
  "quota_used": 50,
  "quota_limit": 500
}
POST/billing/razorpay/order๐Ÿ” Auth Required

Create a Razorpay order for quota purchase.

Request Body

{
  "package_id": "professional"
}

Response

{
  "order_id": "order_xyz123",
  "amount": 399900,
  "currency": "INR",
  "key_id": "rzp_test_xxx"
}
POST/billing/razorpay/verify๐Ÿ” Auth Required

Verify Razorpay payment and add quota.

Request Body

{
  "razorpay_order_id": "order_xyz123",
  "razorpay_payment_id": "pay_abc456",
  "razorpay_signature": "signature_here"
}

Response

{
  "message": "Payment verified, quota added",
  "new_balance": 950
}

Dashboard

Statistics and analytics endpoints.

GET/dashboard/stats๐Ÿ” Auth Required

Get dashboard statistics for the authenticated tenant.

Response

{
  "total_passports": 2500,
  "total_batches": 15,
  "quota_used": 2500,
  "quota_limit": 5000,
  "passports_this_week": 340,
  "pending_export_batches": 2,
  "carbon_compliance_pct": 85.5
}
GET/dashboard/recent-batches๐Ÿ” Auth Required

Get the most recent batches for quick access.

Response

{
  "batches": [
    {
      "id": "batch-uuid",
      "batch_name": "Q1-2026-Production",
      "total_passports": 500,
      "status": "ACTIVE",
      "created_at": "2026-01-15T10:00:00Z"
    }
  ]
}

Passport Lifecycle

Track and manage passport status transitions with tamper-proof audit trail.

POST/passports/{uuid}/transition๐Ÿ” Auth Required

Apply a lifecycle action with automatic event logging.

Request Body

{
  "action": "SHIP",
  "evidence": {
    "shipment_reference": "IND123456789",
    "shipment_date": "2026-01-15"
  }
}

Response

{
  "success": true,
  "previous_status": "ACTIVE",
  "new_status": "SHIPPED",
  "action": "SHIP",
  "event_id": "event-uuid"
}
GET/passports/{uuid}/transitions๐Ÿ” Auth Required

Get allowed lifecycle actions for a passport.

Response

{
  "current_status": "SHIPPED",
  "allowed_actions": ["INSTALL", "RECALL"]
}
GET/passports/{uuid}/events๐Ÿ” Auth Required

Get audit trail with tamper-proof hash chain.

Response

{
  "events": [
    {
      "id": "event-uuid",
      "event_type": "STATUS_CHANGED",
      "action": "SHIP",
      "actor": "admin@acme.com",
      "actor_role": "LOGISTICS",
      "status_from": "ACTIVE",
      "status_to": "SHIPPED",
      "metadata": { "evidence": { "shipment_reference": "IND123456789" } },
      "hash": "sha256:abc123...",
      "previous_hash": "sha256:def456...",
      "created_at": "2026-01-15T10:00:00Z"
    }
  ]
}
POST/passports/bulk/transition๐Ÿ” Auth Required

Bulk transition multiple passports.

Request Body

{
  "passport_ids": ["uuid-1", "uuid-2", "uuid-3"],
  "action": "SHIP",
  "evidence": {
    "shipment_reference": "BATCH-2026-001",
    "shipment_date": "2026-01-15"
  }
}

Response

{
  "total": 3,
  "succeeded": 3,
  "failed": 0,
  "failed_ids": [],
  "errors": []
}

Team Management

Invite team members and manage roles within your organization.

GET/team๐Ÿ” Auth Required

List all team members for the tenant.

Response

{
  "members": [
    {
      "id": "user-uuid",
      "email": "operator@acme.com",
      "role": "operator",
      "status": "active",
      "invited_at": "2026-01-10T10:00:00Z"
    }
  ]
}
POST/team/invite๐Ÿ” Auth Required

Invite a new team member via email.

Request Body

{
  "email": "newuser@acme.com",
  "role": "operator"
}

Response

{
  "message": "Invitation sent",
  "invite_id": "invite-uuid"
}
PUT/team/{id}/role๐Ÿ” Auth Required

Update a team member's role.

Request Body

{
  "role": "admin"
}

Response

{
  "message": "Role updated"
}
DELETE/team/{id}๐Ÿ” Auth Required

Remove a team member.

Response

{
  "message": "Team member removed"
}

Webhooks

Server-side webhook handlers for secure payment processing.

๐Ÿ”’ Secure Payment Processing

Webhooks use HMAC-SHA256 signature verification. Quota is ONLY added via webhook confirmation, not client-side verification.

POST/webhooks/razorpay

Razorpay payment webhook. Verifies signature and adds quota on payment.captured.

Request Body

Headers:
X-Razorpay-Signature: <HMAC-SHA256 signature>

Body:
{
  "event": "payment.captured",
  "payload": {
    "payment": {
      "entity": {
        "id": "pay_abc123",
        "order_id": "order_xyz789",
        "amount": 399900
      }
    }
  }
}

Response

{
  "status": "ok"
}

// Or on signature failure:
HTTP 401 Unauthorized

Error Responses

All error responses follow a consistent format:

{
  "error": "Error message describing what went wrong",
  "code": "ERROR_CODE"
}
400Bad Request - Invalid input data
401Unauthorized - Missing or invalid token
403Forbidden - Insufficient permissions
404Not Found - Resource does not exist
500Internal Server Error