Skip to content

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 User account 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 User is 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 profiles
  • cooling_user_id — required when phone is absent; optional otherwise; must be unique within the operator's company; lowercased before storage

Validation Rules

  • caller must be authenticated as an operator
  • if phone is missing, cooling_user_id is required
  • if phone is provided, it must be unique within the operator's company
  • if cooling_user_id is 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 — missing cooling_user_id for a no-phone profile, or other validation errors
  • 403 Forbidden — unauthenticated or non-operator request
  • 409 Conflict — duplicate cooling_user_id within the same company
{
  "error": "cu_id_taken",
  "message": "A farmer with this CU id already exists in your company."
}

Deprecation note: The old POST /user/v1/farmers/ endpoint previously accepted a create_user boolean flag to switch between self-signup and operator-managed flows. Passing create_user=true now returns a 400 with a deprecation message. Use POST /user/v1/farmers/smartphone-signup/ for self-signup instead.


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.success to 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 in PAYMENT_PENDING status and marks them as expired once their validity period has passed.

For more information on scheduled tasks please refer to this section.