BASE API
⚠️ Note: This page is currently under construction and may be updated with additional details and endpoints.
The BASE API serves as the central backend entry point for the Coldtivate platform. It manages authentication, storage operations, and sensor data, while also orchestrating data processing across other backend services. Built with Django, it uses Celery for background task execution and Valkey for caching.
The BASE API follows a monolithic-but-modular architecture, where different domains of functionality (e.g., marketplace, storage, user, etc.) are implemented as standalone Django apps within the apps/ directory. This modular approach allows for better organization, scalability, and team collaboration.
Cooling User Profile API
Historically, the platform was commonly understood around three non-interchangeable user roles:
- Registered Employee
- Operator
- Cooling User
As the product evolved, especially with the introduction of Marketplace, that model became too rigid for the actual platform behavior.
The backend supports a flexible cooling user profile model with two dedicated endpoints — one for public self-signup and one for operator-managed profile creation. Each has a single, clear responsibility.
The backend derives the cooling user profile type from the resulting profile state:
- smartphone: linked
Useraccount exists - phone: no linked app user, but phone exists
- no-phone: no linked app user and no phone
Endpoints
Cooling User Profiles
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /user/v1/farmers/smartphone-signup/ |
Public + Turnstile | Smartphone self-signup — returns User |
| POST | /user/v1/farmers/ |
Operator auth | Operator-managed profile creation — returns Farmer |
Smartphone Self-Signup
POST /user/v1/farmers/smartphone-signup/
A cooling user creates their own full app account. No authentication required. Cloudflare Turnstile is validated server-side.
Request
{
"user": {
"first_name": "Amina",
"last_name": "Yusuf",
"phone": "+2348012345678",
"email": "[email protected]",
"password": "example-password",
"gender": "F",
"language": "en",
"country": "NG"
},
"turnstile_response": "<token>"
}
Validation Rules
- Turnstile response is required
- if a user with the same phone already exists, the request is rejected (
409)
Outcome
- a full
Useris created and assigned the Farmer role - if an unlinked cooling user profile with the same phone already exists, it is linked to the new user
Response
Returns the created User object.
Operator-Managed Profile Creation
POST /user/v1/farmers/
An authenticated operator creates a cooling user profile in their company. Supports phone-based and no-phone profiles.
Request
{
"first_name": "Ibrahim",
"last_name": "Musa",
"phone": "+2348098765432",
"gender": "M",
"language": "en",
"cooling_user_id": "ibrahim-01"
}
For a no-phone profile, omit or null phone and provide cooling_user_id:
{
"first_name": "Ibrahim",
"last_name": "Musa",
"phone": null,
"gender": "M",
"language": "en",
"cooling_user_id": "cu-ibrahim-01"
}
Field Notes
phone— optional; omit or null for no-phone profilescooling_user_id— required whenphoneis absent; optional otherwise; must be unique within the operator's company; lowercased before storage
Validation Rules
- caller must be authenticated as an operator
- if
phoneis missing,cooling_user_idis required - if
phoneis provided, it must be unique within the operator's company - if
cooling_user_idis provided, it must be unique within the operator's company
Outcome
- a cooling user profile is created in the authenticated operator's company
- if an existing app user already has the submitted phone number, that user is linked to the profile
Response
Returns the created Farmer (cooling user profile) object.
Error Handling
400 Bad Request— missingcooling_user_idfor a no-phone profile, or other validation errors403 Forbidden— unauthenticated or non-operator request409 Conflict— duplicatecooling_user_idwithin the same company
Deprecation note: The old
POST /user/v1/farmers/endpoint previously accepted acreate_userboolean flag to switch between self-signup and operator-managed flows. Passingcreate_user=truenow returns a400with a deprecation message. UsePOST /user/v1/farmers/smartphone-signup/for self-signup instead.
Cooling User Search
GET /user/v1/farmers/?operator=<id>&search=<query>&search_type=<type>
Search Behavior
search_type |
Trigger | Behavior |
|---|---|---|
| (default) | Any text | Searches full name (first + last), phone, and cooling_user_id |
cu_id |
Prefix query with @ (e.g. @cu-001) |
Case-insensitive exact match on cooling_user_id |
phone |
Phone-like pattern (digits + +, spaces, dashes) |
Normalizes and matches against stored phone numbers |
Full name search spans both first_name and last_name — searching "Pablo Mo" will match "Pablo Molina".
Phone search supports partial prefix matching — searching "+351" will match all numbers starting with the Portuguese country code.
Marketplace App
The marketplace app handles marketplace-specific functionality within the Coldtivate platform. This includes order management, payment processing, and background task execution. It is designed to operate independently while interacting with other components of the BASE API.
Documentation for this app includes its models, services, serializers, tasks, views, and endpoints.
Models
The marketplace app defines several models responsible for managing marketplace operations such as crate listings, pricing, orders, coupons, and payment accounts. Below is a brief overview of each model:
CompanyDeliveryContact: Stores delivery contact information for a company.Coupon: Represents a discount coupon that can be used by users or on behalf of a company.MarketListedCrate: Represents a crate listed in the marketplace.MarketListedCratePrice: Stores pricing information for a crate listing.Order: Represents a full order containing one or more crate items.OrderCrateItem: Represents an individual item in an order, tied to a market-listed crate.OrderPickupDetails: Stores pickup preferences for an order item and cooling unit.PaystackAccount: Represents a user's or company’s Paystack subaccount.
Payment Processor
The payment_processor module integrates with Paystack to handle secure payment transactions within the marketplace.
Key Responsibilities
- Fee Calculation: Dynamically computes transaction fees based on Paystack’s pricing structure, including caps, thresholds, and optional international handling.
- Final Amount Computation: Determines the total amount to be charged, including fees, based on a given subtotal using an iterative approach.
- Split Payments: Automatically distributes payments to multiple recipients (e.g., sellers, cooling companies) using Paystack subaccounts and split groups.
- Transaction Initialization: Generates unique references and initiates Paystack transactions with callbacks and metadata.
- Webhook Handling: Listens for Paystack events like
charge.successto update the order status and complete the payment process.
This module ensures a seamless and automated payment experience, while enforcing business rules and maintaining accurate financial records.
Marketplace API Overview
This section documents the REST API endpoints available in the marketplace app. Endpoints are grouped by role (buyer, seller, company) and functionality.
Buyer Endpoints
Cart
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/buyer/cart/ |
Retrieve current cart |
| POST | /marketplace/buyer/cart/ |
Create or recompute cart |
| POST | /marketplace/buyer/cart/set-pickup-details/ |
Set pickup method for cooling units |
| GET | /marketplace/buyer/cart/delivery-contacts/ |
Get delivery contact options |
| POST | /marketplace/buyer/cart/apply-coupon/ |
Apply a discount coupon |
| POST | /marketplace/buyer/cart/clear-coupon/ |
Remove applied coupon |
| POST | /marketplace/buyer/cart/toggle-ownership/ |
Toggle between personal and company cart |
| POST | /marketplace/buyer/cart/checkout-with-paystack/ |
Initiate payment via Paystack |
Cart Items
| Method | Endpoint | Description |
|---|---|---|
| POST | /marketplace/buyer/cart/items/ |
Add produce to cart |
| DELETE | /marketplace/buyer/cart/items/:crate_id/ |
Remove produce from cart |
Orders
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/buyer/orders/ |
List user’s past orders |
| GET | /marketplace/buyer/orders/:order_id/ |
Retrieve order details |
| GET | /marketplace/buyer/orders/:order_id/delivery-contacts/ |
Delivery contact options for order |
| POST | /marketplace/buyer/orders/:order_id/pay-with-paystack/ |
Re-initiate payment |
| POST | /marketplace/buyer/orders/:order_id/cancel/ |
Cancel unpaid order |
Listings
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/buyer/available-listings/ |
Discover active listings nearby |
Seller Endpoints
Listed Crates
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/seller/listed-crates/ |
View active listings |
| GET | /marketplace/seller/listed-crates/:crate_id/ |
View listing details |
| POST | /marketplace/seller/listed-crates/ |
Create/update listings |
| DELETE | /marketplace/seller/listed-crates/:crate_id/ |
Delist a crate |
Coupons
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/seller/coupons/ |
View owned coupons |
| POST | /marketplace/seller/coupons/ |
Create a new coupon |
| GET | /marketplace/seller/coupons/:coupon_id/ |
View coupon details |
| DELETE | /marketplace/seller/coupons/:coupon_id/ |
Revoke a coupon |
Paystack Accounts
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/seller/paystack-accounts/ |
View payout accounts |
| POST | /marketplace/seller/paystack-accounts/ |
Add a payout account |
| GET | /marketplace/seller/paystack-accounts/:id/ |
View account details |
Orders
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/seller/orders/ |
View all paid orders for listings |
Company Endpoints
Company Orders
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/company/orders/?cooling_unit_id=... |
List all paid orders for a given cooling unit |
Delivery Contacts
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/company/delivery-contacts/ |
List company contacts |
| POST | /marketplace/company/delivery-contacts/ |
Create a new contact |
| GET | /marketplace/company/delivery-contacts/legacy/ |
List legacy contacts (no cooling unit linked) |
| GET | /marketplace/company/delivery-contacts/:id/ |
View contact details |
| PATCH | /marketplace/company/delivery-contacts/:id/ |
Partially update a contact |
| DELETE | /marketplace/company/delivery-contacts/:id/ |
Delete a contact |
Setup
| Method | Endpoint | Description |
|---|---|---|
| POST | /marketplace/company/setup/eligibility-check/ |
Check Paystack setup eligibility |
| GET | /marketplace/company/setup/users-paystack-bank-account/?user_id=... |
Fetch user’s Paystack account |
| POST | /marketplace/company/setup/users-first-paystack-bank-account/ |
Create user’s first Paystack account |
Integrations Endpoints
Paystack Webhooks
| Method | Endpoint | Description |
|---|---|---|
| POST | /marketplace/webhooks/paystack/ |
Receive payment events |
Master Data
| Method | Endpoint | Description |
|---|---|---|
| GET | /marketplace/data/banks/ |
List supported Paystack banks |
Scheduled Tasks
The Marketplace app defines two Celery periodic tasks:
-
recompute_computed_fields: recomputes cached and derived fields for marketplace listings to ensure data such as available weight and pending fees is always accurate. -
expire_unpaid_orders: checks for orders stuck inPAYMENT_PENDINGstatus and marks them as expired once their validity period has passed.
For more information on scheduled tasks please refer to this section.