For the complete documentation index, see llms.txt. This page is also available as Markdown.

SPAR Mapper Partner API

This guide walks through setting up the SPAR Mapper Partner API for local development. It covers the full stack: shared libraries, database, application server, and optional Docker-based setup.

Overview

The SPAR (Social Protection Account Registry) Mapper Partner API is a FastAPI service that implements the G2P Connect Mapper specification. It enables linking and resolving a beneficiary's ID (e.g., national ID) to a Financial Address (e.g., mobile wallet or bank account number).

Core capabilities:

  • Link an ID to a Financial Address

  • Resolve an ID to its linked Financial Address

  • Update an existing ID–FA mapping

  • Unlink an ID from a Financial Address

All endpoints require a signed JWT from a trusted issuer (e.g., Keycloak).


Architecture

This is a monorepo with four Python packages under core/:

Package
Path
Role

openg2p-spar-models

core/models/

Shared SQLAlchemy models and Pydantic schemas

openg2p-spar-mapper-core

core/mapper-core/

Mapper business logic, services, helpers

openg2p-spar-mapper-partner-api

core/mapper-partner-api/

FastAPI app exposing the Mapper endpoints

openg2p-spar-bene-portal-api

core/bene-portal-api/

Beneficiary portal API (separate service)

The packages have this dependency chain:

openg2p-fastapi-common (external)

openg2p-spar-models

openg2p-spar-mapper-core

openg2p-spar-mapper-partner-api

Install them in that order.


Prerequisites

Requirement
Version
Notes

Python

3.11+

3.11 is tested in CI

PostgreSQL

15+

Tested with pg 15 in CI

Git

any

Required for installing external deps from GitHub

pip

23+

pip install --upgrade pip before starting

virtualenv

any

Or use python -m venv

System packages (Debian/Ubuntu):

macOS (Homebrew):


Repository Setup

The working directory for all commands below is the repo root (spar/) unless stated otherwise.


Python Environment

Create and activate a virtual environment at the repo root:

Upgrade pip and build tools before installing packages:


Install Dependencies

Dependencies must be installed in the correct order because each package depends on the one before it.

External OpenG2P FastAPI Common Libraries

These are hosted in a separate GitHub repository. Pin to the same ref used in the Dockerfile (v1.1.5):

Note: Installing openg2p-fastapi-partner-auth is required even though it is not listed in pyproject.toml directly — it is a runtime dependency for JWT validation.

Local SPAR Packages (editable installs)

Install in dependency order:

Editable installs (-e) mean any local code changes are immediately reflected without reinstalling.

Test Dependencies (optional, for running tests)


Database Setup

Create Database and User

Connect to PostgreSQL and run:

Or as a one-liner using psql:

Verify Connection


Environment Configuration

The application reads configuration from environment variables (or a .env file in the working directory). All variables use the prefix SPAR_MAPPER_PARTNER_API_.

Create a .env file inside core/mapper-partner-api/:

Edit the file with your local values:

Configuration Reference

Variable
Default
Description

SPAR_MAPPER_PARTNER_API_HOST

0.0.0.0

Bind address

SPAR_MAPPER_PARTNER_API_PORT

8000

Listen port

SPAR_MAPPER_PARTNER_API_NO_OF_WORKERS

1

Gunicorn worker count

SPAR_MAPPER_PARTNER_API_WORKER_TYPE

gunicorn

Server type

SPAR_MAPPER_PARTNER_API_OPENAPI_ROOT_PATH

/api/mapper

OpenAPI root path

SPAR_MAPPER_PARTNER_API_DB_HOSTNAME

localhost

PostgreSQL host

SPAR_MAPPER_PARTNER_API_DB_PORT

5432

PostgreSQL port

SPAR_MAPPER_PARTNER_API_DB_USERNAME

postgres

Database user

SPAR_MAPPER_PARTNER_API_DB_PASSWORD

password

Database password

SPAR_MAPPER_PARTNER_API_DB_DBNAME

spardb

Database name

SPAR_MAPPER_PARTNER_API_DEFAULT_ISSUERS

JSON array of trusted JWT issuers

SPAR_MAPPER_PARTNER_API_DEFAULT_JWKS_URLS

JSON array of JWKS endpoint URLs

SPAR_MAPPER_PARTNER_API_JWT_AUTH_ENABLED

false

Verify the partner JWS signature on every request

SPAR_MAPPER_PARTNER_API_CRYPTO_BACKEND

partner-mgmt

Verify backend: partner-mgmt (fetch keys from Partner Manager). local is a legacy option

SPAR_MAPPER_PARTNER_API_CRYPTO_ALLOWED_ALGORITHMS

RS256

Allowed JWS algorithms (RS256 only; none/HMAC rejected)

SPAR_MAPPER_PARTNER_API_PARTNER_MGMT_API_URL

Partner Manager key-fetch base URL (GET {url}/keys/PARTNER_<MNEMONIC>)

Local dev tip: For development without Keycloak, you can configure the JWT validation to accept a self-signed token by pointing DEFAULT_JWKS_URLS at a local mock JWKS endpoint.


Run Migrations

The application manages its own schema through an in-app migration command. Run this once after creating the database, and again after pulling changes that modify models.

This creates (or updates) the id_fa_mapping and strategy tables in the configured database.


Start the Server

From the core/mapper-partner-api/ directory:

Development mode (uvicorn with auto-reload):

Production-like mode (gunicorn + uvicorn workers):

Once running, the API is available at:

URL
Description

http://localhost:8000/docs

Swagger UI (interactive API docs)

http://localhost:8000/redoc

ReDoc API documentation

http://localhost:8000/openapi.json

Raw OpenAPI schema

http://localhost:8000/ping

Health check endpoint


API Endpoints

All mapper endpoints are under the /mapper prefix and require a valid JWT in the Authorization: Bearer <token> header.

Method
Path
Description

POST

/mapper/link

Link an ID to a Financial Address

POST

/mapper/resolve

Resolve an ID to its Financial Address

POST

/mapper/update

Update an existing ID–FA mapping

POST

/mapper/unlink

Remove an ID–FA mapping

All requests and responses follow the G2P Connect Mapper API specification.


Running Tests

Install test dependencies if you haven't already:

A running PostgreSQL instance is required for integration tests. Set the test database connection via environment variables before running:

Run tests from the relevant module directory:


Code Quality

The project uses pre-commit hooks to enforce code style.

Install Pre-commit Hooks

Run Manually

Tools Used

Tool
Purpose

Code formatting

Fast linting (replaces flake8, isort)

Modernise Python syntax

Ruff config: core/.ruff.toml — line length 110, checks: E, W, F, I, C, B.


Docker Build & Run

Build the Image

The Docker build context must be the repo root (not the api subdirectory), as the Dockerfile copies multiple packages:

To pin a specific version of the external FastAPI common library:

Run the Container

On Linux, replace host.docker.internal with 172.17.0.1 (the default Docker bridge gateway) or use --network host.

The container automatically runs python main.py migrate on startup before launching gunicorn.

Container Environment Variables

All SPAR_MAPPER_PARTNER_API_* variables from the Configuration Reference section work as container environment variables.

Variable
Container Default

SPAR_MAPPER_PARTNER_API_HOST

0.0.0.0

SPAR_MAPPER_PARTNER_API_PORT

8000

SPAR_MAPPER_PARTNER_API_NO_OF_WORKERS

4


Troubleshooting

ModuleNotFoundError: No module named 'openg2p_fastapi_partner_auth'

The partner-auth library is not installed automatically via pyproject.toml. Install it explicitly:

asyncpg.exceptions.InvalidCatalogNameError: database "spardb" does not exist

The database has not been created yet. Follow Section 7 to create it.

FATAL: password authentication failed for user "spar_user"

Check that:

  1. The SPAR_MAPPER_PARTNER_API_DB_PASSWORD env var matches the password set during database creation.

  2. PostgreSQL pg_hba.conf allows password-based authentication for local connections (use md5 or scram-sha-256).

sqlalchemy.exc.ProgrammingError: relation "id_fa_mapping" does not exist

Migrations have not been run. Execute:

JWT Validation Errors (401 Unauthorized)

  • Verify SPAR_MAPPER_PARTNER_API_DEFAULT_ISSUERS matches the iss claim in your JWT.

  • Verify SPAR_MAPPER_PARTNER_API_DEFAULT_JWKS_URLS points to a reachable JWKS endpoint.

  • For local dev without Keycloak, check the G2P FastAPI Auth library docs for configuring a bypass or test mode.

Pre-commit Hooks Failing on black or ruff

Run formatting and linting manually, then re-stage:

Last updated

Was this helpful?