← back to projects
backendapiaiin-progress

AgroNet — Agricultural Marketplace API

A mobile backend REST API that connects Nigerian farmers directly to buyers, eliminating middlemen from the agricultural supply chain.

GitHub ↗Live Demo ↗

The Problem

Smallholder farmers in Nigeria lack direct access to buyers, forcing them to sell through middlemen who take large margins. AgroNet removes that layer by giving farmers a platform to list produce and negotiate directly with buyers.

My Approach

Built a layered Django REST Framework API following a strict Views → Services → Models architecture. Business logic lives exclusively in service modules, keeping views thin and testable. Role-based access control (farmer/buyer) is enforced at the permission layer using custom DRF permission classes. JWT authentication gates every endpoint. External integrations (Interswitch payments, Google Vision image classification, TensorFlow price prediction) are isolated in dedicated service modules.

Challenges & Solutions

Designing a clean state machine for the order lifecycle (pending → confirmed → paid → completed) that prevents illegal state transitions. Integrating Interswitch's payment gateway in a sandbox environment with limited documentation. Keeping the AI price prediction and image classification services decoupled from core business logic so they can fail gracefully without breaking the main flow.

Results & Impact

Fully functional REST API covering auth, product listings, offer negotiation, payment processing, AI price prediction, and image classification. Comprehensive test suite including property-based tests (Hypothesis) validating correctness properties across randomised inputs.

Architecture Overview

Layered REST API with a strict Views → Services → Models separation. Five domain apps (users, products, orders, payments, ai) each own their models, serializers, views, services, and permissions. All external API calls are isolated in service modules.

Tech Stack

Python 3.11Django 6Django REST FrameworkPostgreSQLJWT (SimpleJWT)InterswitchGoogle Vision APITensorFlowCloudinaryDockerGunicorndrf-spectacular

API Showcase

POST/api/auth/token/

Obtain a JWT access + refresh token pair using email and password.

{ "access": "<jwt>", "refresh": "<jwt>" }
POST/api/users/register/

Register a new user with a farmer or buyer role.

{ "id": "uuid", "email": "user@example.com", "role": "farmer" }
GET/api/products/auth

Paginated list of available produce listings with filtering and search.

{ "count": 42, "next": "...", "results": [ { "id": "uuid", "title": "Fresh Tomatoes", "price_per_unit": "300.00" } ] }
POST/api/products/auth

Create a new produce listing. Restricted to farmers.

{ "id": "uuid", "title": "Fresh Tomatoes", "is_available": true }
GET/api/products/my/auth

Retrieve the authenticated farmer's own product listings (available and unavailable), newest first.

{ "count": 5, "next": null, "results": [ { "id": "uuid", "title": "Yam", "is_available": false } ] }
POST/api/orders/auth

Buyer places an offer on a product, creating an order in pending state.

{ "id": "uuid", "status": "pending", "product": "uuid", "offered_price": "250.00" }
PATCH/api/orders/{id}/auth

Farmer confirms or declines an order; buyer triggers payment to advance state.

{ "id": "uuid", "status": "confirmed" }
POST/api/payments/auth

Initiate an Interswitch payment for a confirmed order.

{ "payment_url": "https://sandbox.interswitchng.com/...", "reference": "TXN-uuid" }
POST/api/ai/predict-price/auth

Get a TensorFlow-based price prediction for a given crop type and quantity.

{ "predicted_price": "320.00", "currency": "NGN" }
POST/api/products/{id}/image/auth

Upload a product image; Google Vision classifies the crop and Cloudinary stores it.

{ "image_url": "https://res.cloudinary.com/..." }

Deployment

Platform

Docker / Gunicorn

Docker

Yes