Skip to content

NUMU-IO/NUMU-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1,032 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

NUMU API

The core backend for NUMU β€” a multi-tenant SaaS e-commerce platform purpose-built for the Egyptian and MENA market ("Shopify for Egypt"). Built with FastAPI and Clean Architecture, with PostgreSQL Row-Level Security for tenant isolation and a Celery worker fleet for background jobs.

Every NUMU frontend (merchant hub, admin backoffice, customer storefront, landing page) talks to this single API.


Table of contents


System architecture

flowchart TB
  subgraph Clients["NUMU clients"]
    LP[numu-landing-page]
    MH[numo-merchant-hub]
    AD[numu-admin]
    SF[numu-storefront Β· V3 BYOT]
    BZ[numu-egyptian-bazaar Β· V2]
    MA[numu-merchant-app Β· Expo]
    PI[numu-payments-intelligence Β· Shopify app]
  end

  subgraph API["NUMU-api Β· FastAPI"]
    HTTP[HTTP layer<br/>routes Β· middleware]
    APP[Application layer<br/>use cases Β· DTOs]
    CORE[Core domain<br/>entities Β· value objects]
    INFRA[Infrastructure<br/>repositories Β· adapters]
  end

  subgraph Storage["Storage"]
    DB[(PostgreSQL Β· RLS)]
    R[(Redis Β· cache + Celery broker)]
    OS[(Object storage Β· R2/S3/MinIO)]
  end

  subgraph Workers["Celery workers"]
    W1[default queue]
    W2[images queue]
    W3[notifications]
  end

  subgraph External["External services"]
    PM[Paymob Β· Fawry Β· InstaPay<br/>Kashier Β· Moyasar Β· Tap Β· JT Β· Stripe]
    BO[Bosta Β· MyLerz Β· Shippo]
    RS[Resend Β· Twilio]
    WA[WhatsApp Business]
    MT[Meta Β· Pixel/CAPI/OAuth]
    OAI[OpenAI Β· HF Vision OCR]
    ETA[ETA Egypt Β· ZATCA Saudi Β· Fawaterak]
    SE[Sentry / Slack]
  end

  Clients -- "REST Β· httpOnly cookies" --> HTTP
  HTTP --> APP --> CORE
  APP --> INFRA
  INFRA --> DB
  INFRA --> R
  INFRA --> OS
  R --> Workers
  Workers --> RS
  Workers --> WA
  Workers --> SE
  INFRA --> PM
  INFRA --> BO
  INFRA --> MT
  INFRA --> OAI
  INFRA --> ETA
Loading

Clean Architecture layering

Strict, one-way dependencies β€” never reverse them.

flowchart LR
  subgraph L["Dependency direction"]
    direction LR
    api[api/<br/>routes Β· middleware] --> application[application/<br/>use cases Β· DTOs] --> core[core/<br/>entities Β· interfaces]
    api --> infrastructure[infrastructure/<br/>DB Β· adapters Β· cache]
    application --> infrastructure
    infrastructure -.implements.-> core
  end
Loading
Layer Responsibility Allowed imports
core/ Pure domain β€” entities, value objects, exceptions, interfaces (nothing internal)
application/ Use cases + DTOs core/ only
infrastructure/ DB models, repositories, external services, cache, Celery tasks core/ (implements interfaces)
api/ HTTP routes, middleware, FastAPI deps, Pydantic schemas All inner layers via DI

Request lifecycle

sequenceDiagram
    actor U as Client
    participant MW as Middleware stack
    participant R as FastAPI route
    participant UC as Use case
    participant Repo as Repository
    participant DB as PostgreSQL (RLS)
    participant C as Redis
    participant E as External service

    U->>MW: HTTP request (host: shop.numueg.app)
    Note over MW: CORS β†’ Logging β†’ Tenant β†’ CSRF<br/>ResponseTime β†’ Sentry β†’ RateLimit<br/>Compression β†’ CacheHeaders β†’ SecurityHeaders
    MW->>MW: resolve tenant from subdomain<br/>SET app.current_tenant
    MW->>R: dispatch
    R->>UC: validate Pydantic schema Β· invoke use case
    UC->>Repo: load entities
    Repo->>DB: SELECT … (RLS filters by tenant)
    DB-->>Repo: rows
    UC->>C: read/write cache (optional)
    UC->>E: outbound call (optional Β· Paymob, OpenAI, …)
    UC-->>R: result DTO
    R-->>MW: serialize response
    MW-->>U: HTTP response (with security + cache headers)
Loading

Multi-tenancy

Shared schema + PostgreSQL Row-Level Security. Every tenant-scoped model carries a tenant_id foreign key, and the tenant middleware sets app.current_tenant per-request so RLS policies filter automatically.

flowchart LR
  Sub["shop.numueg.app"] --> M[TenantMiddleware]
  M -- "resolve subdomain" --> T[(public.tenants)]
  M -- "SET app.current_tenant = ..." --> Conn[(per-request DB connection)]
  Conn -- "every SELECT/UPDATE filtered<br/>by RLS USING (tenant_id = current_tenant)" --> Tables[(tenant-scoped tables)]
Loading

Tech stack

Layer Choice
Language Python 3.11+
Framework FastAPI (async)
ORM SQLAlchemy 2.0 (async)
Validation Pydantic v2
Database PostgreSQL 15+ (Row-Level Security)
Cache / broker Redis 7+
Background jobs Celery
Migrations Alembic
Auth JWT RS256 (access 30m + refresh 7d) Β· CSRF double-submit
Logging structlog (JSON in prod, console in dev)
Admin panel SQLAdmin (session-cookie auth)
PDF WeasyPrint + Jinja2 (Noto Sans Arabic)
Encryption AES-256-GCM (merchant credentials at rest)

Quick start

Prerequisites: Python 3.11+, PostgreSQL 15+, Redis 7+.

# 1. Clone and install dependencies
git clone <repository-url>
cd NUMU-api
pip install -e ".[dev]"

# 2. Configure environment
cp .env.example .env

# 3. Start dependencies via Docker
docker compose -f docker/docker-compose.yml up -d db redis

# 4. Run migrations
alembic upgrade head

# 5. (optional) Seed sample data
python scripts/seed_data.py

# 6. Start the dev server
make dev   # or: uvicorn src.main:app --reload --port 8000

Full stack via Docker Compose:

docker compose -f docker/docker-compose.yml up --build

API docs

Once running, the auto-generated docs live at:

URL UI
http://localhost:8000/docs Swagger UI
http://localhost:8000/redoc ReDoc
http://localhost:8000/admin SQLAdmin web panel (session-cookie auth)

Routes are grouped under /api/v1/:

Prefix Domain
/auth/ Register Β· login Β· refresh Β· logout Β· CSRF Β· 2FA Β· email verification Β· password reset
/stores/ Store CRUD (owner)
/stores/{id}/… Commerce: products Β· variants Β· categories Β· orders (+drafts Β· import Β· returns Β· refunds) Β· customers Β· inventory (+levels Β· transfers) Β· locations Β· gift_cards Β· bundles Β· shipments Β· shipping (+zones)
/stores/{id}/… Growth: coupons Β· promotions (offers v2) Β· marketing campaigns/audiences Β· email_templates Β· upsells Β· abandoned_checkouts Β· social Β· analytics (+realtime) Β· dashboard Β· ai
/stores/{id}/… Content: menus Β· pages Β· settings Β· onboarding Β· invoices Β· payment_proofs Β· payments Β· reconciliation Β· apps Β· order_import
/stores/{id}/… WhatsApp & omnichannel: whatsapp (+campaigns Β· chat Β· templates Β· opt_ins Β· scheduled_sends) Β· channels Β· threads Β· messages Β· capi
/stores/{id}/… Themes V3: themes Β· theme_editor_v3 Β· theme_installations Β· theme_updates Β· customizer_undo
/themes + /marketplace/ Theme marketplace: upload/build Β· developer submissions Β· admin review Β· catalog Β· purchases Β· reviews Β· store install
/storefront/store/{id}/ Public catalog Β· search Β· reviews Β· customer auth Β· checkout (+session) Β· gift cards Β· shipping rates Β· locations Β· payment proofs Β· pay Β· tracking
/storefront/me/ Customer profile Β· addresses Β· cart Β· checkout Β· wishlist Β· returns Β· saved cards Β· data rights
/storefront/… store-by-subdomain/{subdomain} Β· theme_resolution Β· meta_feed (Meta Commerce XML)
/staff/ + /roles + /permissions Staff invitations Β· sessions Β· access requests Β· policies Β· RBAC
/admin/ Super-admin: tenants, waitlist, feedback, dashboard, platform config
/tenants/ Β· /public/ Tenant registration & subdomain check Β· waitlist Β· landing config
/billing Β· /referrals Β· /risk Subscriptions Β· merchant referrals Β· trust-network risk
/shopify/ Shopify app surface (11 sub-routers)
/oauth/meta Meta OAuth for business scopes
/webhooks/ paymob Β· fawry Β· instapay Β· kashier Β· moyasar Β· jt Β· bosta Β· mylerz Β· meta Β· whatsapp Β· fawaterak Β· resend
/ws Β· /health WebSocket realtime (inbox) Β· liveness probe

Configuration

Variable Description Default
DEBUG Enable debug mode false
DATABASE_URL PostgreSQL connection string required
REDIS_URL Redis connection string required
JWT_PRIVATE_KEY RSA private key (PEM) required
JWT_PUBLIC_KEY RSA public key (PEM) required
STRIPE_SECRET_KEY Stripe API key optional
RESEND_API_KEY Resend email API key optional
OPENAI_API_KEY OpenAI API key optional
R2_ACCESS_KEY_ID Cloudflare R2 access key optional
META_APP_ID Meta (Facebook / Instagram) App ID optional
META_APP_SECRET Meta App Secret optional
META_WEBHOOK_VERIFY_TOKEN Webhook verification token optional
META_GRAPH_API_VERSION Graph API version v21.0
META_LOGIN_CONFIG_ID Facebook Login Config ID optional
INBOX_REALTIME_ENABLED Enable WebSocket inbox true
NOMINATIM_URL Self-hosted Nominatim base URL optional
LOCATIONIQ_KEY LocationIQ key (used if Nominatim unset) optional

See src/config/settings.py for the complete list.


External services

Category Services
Payments Paymob (cards + wallets) Β· Fawry Β· InstaPay Β· Kashier Β· Moyasar Β· Tap Β· JT Β· Stripe Β· Cash on Delivery
Shipping Bosta Β· MyLerz (Egyptian couriers) Β· Shippo
Email / SMS Resend Β· Twilio
Messaging WhatsApp Business API (templates Β· campaigns Β· omnichannel inbox)
Marketing Meta β€” Pixel, Conversions API, OAuth, custom/lookalike audiences, Messenger/Instagram inbox
Storage Cloudflare R2 / MinIO / AWS S3
AI OpenAI (product descriptions, insights) Β· Hugging Face Vision (payment-proof OCR)
Tax / e-invoicing ETA (Egypt) Β· ZATCA (Saudi Arabia) Β· Fawaterak
Maps Self-hosted Nominatim (or) LocationIQ
Monitoring Sentry Β· Slack (webhook channels, batched every 30s)

Self-hosted Nominatim

The storefront checkout location picker calls /storefront/.../geocode/reverse, which proxies to either a self-hosted Nominatim container or LocationIQ depending on env config.

docker compose --profile geocoding up nominatim

The first run downloads ~200 MB and imports the Egypt OSM extract (~5 GB on disk, ~30 min). Subsequent restarts come up in seconds. The container runs UPDATE_MODE=continuous against Geofabrik's daily Egypt diff feed β€” no Celery task or manual re-import required.


Background jobs

flowchart LR
  API[NUMU-api] -- enqueue --> R[(Redis broker)]
  R --> W[Celery workers<br/>~57 task modules]
  W --> Email[Resend email]
  W --> WA[WhatsApp Business]
  W --> Slack[Slack webhooks Β· batched 30s]
  W --> Store[(R2 / S3 / MinIO)]
  W --> Meta[Meta CAPI]
Loading
Area Tasks (selection)
Commerce abandoned-cart recovery Β· back-in-stock Β· shipments Β· order webhooks
WhatsApp campaign sends Β· scheduled dispatcher (60s) Β· template poll (15m) Β· dead-letter purge (daily)
Payments / risk InstaPay expiry Β· COD deposit expiry Β· auto-RTO Β· risk scoring Β· fraud detection
Marketing campaigns Β· promotions Β· Meta CAPI dispatch Β· social
Analytics daily rollups Β· event ingest Β· retention purge Β· courier stats
Themes theme build Β· upload Β· marketplace tasks
Lifecycle demo cleanup Β· trial expiry Β· data retention Β· daily DB backup (03:00 UTC) Β· image processing

Project structure

Show tree
NUMU-api/
β”œβ”€β”€ alembic/                   # Database migrations
β”œβ”€β”€ docker/                    # Docker configuration
β”œβ”€β”€ docs/                      # Documentation
β”œβ”€β”€ scripts/                   # Utility scripts (seed, ops, etc.)
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ dependencies/      # FastAPI Depends() factories
β”‚   β”‚   β”œβ”€β”€ middleware/        # CORS, logging, tenant, CSRF, etc.
β”‚   β”‚   β”œβ”€β”€ responses/         # Response envelopes
β”‚   β”‚   └── v1/
β”‚   β”‚       β”œβ”€β”€ routes/        # API endpoints grouped by domain
β”‚   β”‚       └── schemas/       # Pydantic request/response schemas
β”‚   β”œβ”€β”€ application/
β”‚   β”‚   β”œβ”€β”€ dto/               # Data transfer objects
β”‚   β”‚   β”œβ”€β”€ services/          # Application services
β”‚   β”‚   └── use_cases/         # Business use cases
β”‚   β”œβ”€β”€ config/                # Pydantic settings management
β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”œβ”€β”€ entities/          # Domain entities
β”‚   β”‚   β”œβ”€β”€ exceptions/        # Domain exceptions
β”‚   β”‚   β”œβ”€β”€ interfaces/        # Repository + service interfaces
β”‚   β”‚   └── value_objects/     # Money, LocalizedString, etc.
β”‚   └── infrastructure/
β”‚       β”œβ”€β”€ cache/             # Redis cache
β”‚       β”œβ”€β”€ database/          # SQLAlchemy setup + ORM models
β”‚       β”œβ”€β”€ external_services/ # Paymob, Bosta, OpenAI, …
β”‚       β”œβ”€β”€ messaging/         # Celery tasks
β”‚       └── repositories/      # Repository implementations
└── tests/
    β”œβ”€β”€ unit/                  # Unit tests
    β”œβ”€β”€ integration/           # Integration tests (real DB / Redis)
    └── e2e/                   # End-to-end tests

Testing

pytest                                    # full suite
pytest --cov=src --cov-report=html        # with coverage
pytest tests/unit/                        # unit only
pytest tests/integration/                 # integration only
pytest tests/e2e/                         # end-to-end only

Development tools

ruff format src/ tests/    # format
ruff check src/ tests/     # lint
mypy src/                  # type check
make migrate-new           # generate a new Alembic migration
make migrate               # apply migrations
make seed                  # seed sample data

License

MIT.

About

πŸ›’ Modern e-commerce API built with FastAPI & Clean Architecture. Features JWT auth, Stripe/Tap payments, Shippo shipping, OpenAI integration, and Cloudflare R2 storage. PostgreSQL + Redis. Fully typed, tested, and production-ready.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors