Open Source School Marketplace

Build with Trade Buddy

A fully typed TypeScript SDK, REST API, and open source codebase. Build integrations for the school marketplace.

$ npm install @tradebuddy/sdk Click to copy
Quick Start API Reference GitHub Quill

Quick Start
Up and running in 60 seconds
Install the SDK, authenticate, and start fetching listings in just a few lines of TypeScript.
1

Install the SDK

Add the Trade Buddy SDK to your project with npm or yarn.

2

Authenticate

Sign in with email and password to get a session token.

3

Fetch listings

Query the marketplace for products, donations, or wanted items.

4

Create a listing

Post a new item to the marketplace programmatically.

index.ts
// Step 1: Install
// Run in your terminal:

npm install @tradebuddy/sdk

// or with yarn:
yarn add @tradebuddy/sdk

// TypeScript types are included out of the box.
// No @types package needed.
import { TradeBuddy } from '@tradebuddy/sdk';

// Create a client instance
const client = new TradeBuddy();

// Authenticate with email and password
const session = await client.signIn({
  email: 'jane@school.edu',
  password: 'your-password',
});

console.log(session.user.name); // "Jane Doe"
console.log(session.token);     // "eyJhbG..."
// Fetch all listings from the marketplace
const listings = await client.getListings();

// Each listing is fully typed
listings.forEach((item: Listing) => {
  console.log(item.title);      // "School Blazer"
  console.log(item.type);       // "Sell" | "Donate" | "Wanted"
  console.log(item.price);      // 25
  console.log(item.category);   // "School Uniform"
});

// Filter by type
const donations = listings.filter(
  l => l.type === 'Donate'
);
// Create a new listing
const newListing = await client.createListing({
  title: 'Graphing Calculator',
  type: 'Sell',
  price: 35,
  category: 'Electronics',
  condition: 'Like New',
  description: 'TI-84 Plus, barely used',
});

console.log(newListing.id);  // "sell_42"

// Delete your account (careful!)
await client.deleteAccount();

API Reference
REST API
Authenticate users, manage listings, and interact with the marketplace.
API Operational
Authentication
POST Sign Up
POST Sign In
POST Sign Out
DEL Delete Account
Listings
GET All Listings
POST Create Listing
Sign Up
Create a new user account. Returns a Bearer token for authenticated requests.
No auth required
POSThttps://mytradebuddy.com/api/auth.php?action=signup
ParameterTypeDescription
name requiredstringFull name of the user
email requiredstringUser's email address
password requiredstringAccount password
import { TradeBuddy } from '@tradebuddy/sdk';

const client = new TradeBuddy();

const session = await client.signUp({
  name: 'Jane Doe',
  email: 'jane@school.edu',
  password: 'secure-password',
});

console.log(session.user);  // { id: 42, name: "Jane Doe", ... }
console.log(session.token); // Bearer token
curl -X POST https://mytradebuddy.com/api/auth.php?action=signup \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Doe",
    "email": "jane@school.edu",
    "password": "secure-password"
  }'
{
  "success": true,
  "user": {
    "id": 42,
    "name": "Jane Doe",
    "email": "jane@school.edu"
  },
  "token": "eyJhbGciOiJIUzI1NiJ9..."
}
Sign In
Authenticate an existing user and receive a Bearer token.
No auth required
POSThttps://mytradebuddy.com/api/auth.php?action=login
ParameterTypeDescription
email requiredstringRegistered email address
password requiredstringAccount password
const session = await client.signIn({
  email: 'jane@school.edu',
  password: 'secure-password',
});

// Session is now active
console.log(session.user.name); // "Jane Doe"
curl -X POST https://mytradebuddy.com/api/auth.php?action=login \
  -H "Content-Type: application/json" \
  -d '{ "email": "jane@school.edu", "password": "secure-password" }'
{
  "success": true,
  "user": { "id": 42, "name": "Jane Doe", "email": "jane@school.edu" },
  "token": "eyJhbGciOiJIUzI1NiJ9..."
}

Try it live

Connected
Response
Sign Out
Invalidate the current session token.
Bearer token required
POSThttps://mytradebuddy.com/api/auth.php?action=logout
await client.signOut();
// Token is now invalidated on the server
curl -X POST https://mytradebuddy.com/api/auth.php?action=logout \
  -H "Authorization: Bearer YOUR_TOKEN"
Delete Account
Permanently delete a user account and all associated listings. Cannot be undone.
Bearer token required
DELhttps://mytradebuddy.com/api/account.php?action=delete
// Permanently deletes account + all listings
await client.deleteAccount();
// All user data removed from database
curl -X POST https://mytradebuddy.com/api/account.php?action=delete \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Account deleted successfully"
}
Get All Listings
Retrieve all marketplace listings. Returns products, donations, and wanted items.
No auth required
GEThttps://mytradebuddy.com/api/listings.php
const listings = await client.getListings();

listings.forEach((item: Listing) => {
  console.log(`${item.title} — $${item.price}`);
  console.log(`${item.category} | ${item.condition}`);
  console.log(`Seller: ${item.sellerName}`);
});
curl https://mytradebuddy.com/api/listings.php
{
  "success": true,
  "listings": [
    {
      "id": "sell_17",
      "type": "Sell",
      "title": "Sixth Form Uniform",
      "price": 40,
      "category": "School Uniform",
      "condition": "Good",
      "sellerName": "Arhan Harchandani",
      "createdAt": 1773280792000
    }
  ]
}

Try it live

Response
Create Listing
Post a new item to the marketplace.
Bearer token required
POSThttps://mytradebuddy.com/api/listings.php
ParameterTypeDescription
title requiredstringItem title
type required"Sell" | "Donate" | "Wanted"Listing type
price optionalnumberPrice (Sell only)
category requiredstringOne of 12 categories
condition requiredstringNew, Like New, Good, Fair
description optionalstringAdditional details
const listing = await client.createListing({
  title: 'Graphing Calculator',
  type: 'Sell',
  price: 35,
  category: 'Electronics',
  condition: 'Like New',
  description: 'TI-84 Plus, barely used.',
});

console.log(listing.id); // "sell_42"
curl -X POST https://mytradebuddy.com/api/listings.php \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Graphing Calculator",
    "type": "Sell",
    "price": 35,
    "category": "Electronics",
    "condition": "Like New"
  }'
{
  "success": true,
  "id": "sell_42"
}

API Testing
Our API is tested with Quill
38 automated tests validate authentication, listings, data integrity, and response shape — written in plain English using Quill.
tradebuddy-tests.quill
-- Authentication Tests

test "login with invalid credentials returns failure":
  response is await postJSON("{api_url}/auth.php?action=login", {
    email: "fake@nonexistent.com",
    password: "wrongpassword123"
  })
  expect response.success is no

-- Listings Tests

test "each listing has a valid type":
  data is await fetchJSON("{api_url}/listings.php")
  for each item in data.listings:
    expect isValidType(item.type) is yes

-- Data Integrity

test "no duplicate listing IDs":
  data is await fetchJSON("{api_url}/listings.php")
  ids is map_list(data.listings, with i: i.id)
  expect length(unique(ids)) is length(ids)
View Full Test Suite (38 tests) View on GitHub

TypeScript SDK
@tradebuddy/sdk
A fully typed TypeScript client for the Trade Buddy API. Zero dependencies, tree-shakeable, works everywhere.
types.ts
interface TradeBuddyConfig {
  baseUrl?: string;   // default: "https://mytradebuddy.com/api"
  token?: string;     // optional: resume a session
}

interface User {
  id: number;
  name: string;
  email: string;
}

interface Session {
  user: User;
  token: string;
}

interface Listing {
  id: string;
  type: 'Sell' | 'Donate' | 'Wanted';
  title: string;
  price: number;
  category: Category;
  condition: Condition;
  description?: string;
  imageUri?: string;
  sellerName: string;
  sellerEmail: string;
  createdAt: number;
}

type Category =
  | 'Books' | 'Electronics' | 'Clothing & Accessories'
  | 'School Uniform' | 'Sports Equipment' | 'Toys'
  | 'Video Games' | 'Board Games' | 'Furniture'
  | 'Kitchen Items' | 'Household Items'
  | 'Jewelry & Watches';

type Condition = 'New' | 'Like New' | 'Good' | 'Fair';

Fully Typed

TypeScript types for every request and response

Zero Dependencies

Uses native fetch — Node, Deno, Bun, browsers

Token Management

Handles Bearer tokens automatically after sign in

Tree-Shakeable

Import only what you need — minimal bundle


Real-Time Events
Webhooks
Subscribe to events and get HTTP POST notifications in real time. Never poll the API again.

Available Events

listing.created A new listing is posted
listing.sold A listing is marked as sold
listing.deleted A listing is removed
user.created A new user signs up
user.deleted A user deletes their account
// POST to your endpoint
{
  "event": "listing.created",
  "timestamp": 1711843200000,
  "data": {
    "id": "sell_42",
    "type": "Sell",
    "title": "Graphing Calculator",
    "price": 35,
    "category": "Electronics",
    "condition": "Like New",
    "sellerName": "Jane Doe",
    "sellerEmail": "jane@school.edu"
  }
}
import { TradeBuddy } from '@tradebuddy/sdk';

const client = new TradeBuddy();
await client.signIn({ email, password });

// Register a webhook endpoint
const webhook = await client.createWebhook({
  url: 'https://yourapp.com/webhooks/tradebuddy',
  events: [
    'listing.created',
    'listing.sold',
    'user.created',
  ],
  secret: 'whsec_your_secret_here',
});

console.log(webhook.id);  // "wh_abc123"
import crypto from 'crypto';

// Verify webhook signature in your handler
function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

// Express handler example
app.post('/webhooks/tradebuddy', (req, res) => {
  const sig = req.headers['x-tradebuddy-signature'];
  if (!verifyWebhook(req.body, sig, 'whsec_...')) {
    return res.status(401).send('Invalid signature');
  }
  const event = JSON.parse(req.body);
  console.log(event.event); // "listing.created"
  res.status(200).send('ok');
});

HMAC Signatures

Every payload is signed with SHA-256 for verification

Selective Events

Subscribe only to the events you care about

Auto-Retry

Failed deliveries are retried with exponential backoff

Delivery Logs

View request/response history for every delivery attempt


Authentication
Developer API Keys
Dedicated API keys for third-party apps with scoped permissions, rate limiting, and usage analytics.

Production Key

Full access — listings, users, webhooks

tb_live_sk_7f3a... Secret

Test Key

Sandbox — no real data affected

tb_test_sk_9c2b... Test

Public Key

Read-only — listings and categories

tb_live_pk_4d1e... Public

Rate Limits

Production1,000 req/min
Test100 req/min
Public60 req/min
import { TradeBuddy } from '@tradebuddy/sdk';

// Authenticate with an API key instead of email/password
const client = new TradeBuddy({
  apiKey: 'tb_live_sk_7f3a...',
});

// All methods work the same way
const listings = await client.getListings();

// Public keys are read-only
const publicClient = new TradeBuddy({
  apiKey: 'tb_live_pk_4d1e...',
});
const items = await publicClient.getListings(); // ✓ works
// publicClient.createListing(...)  // ✗ 403 Forbidden
# Use API key in the Authorization header
curl https://mytradebuddy.com/api/listings.php \
  -H "Authorization: Bearer tb_live_sk_7f3a..."

# Check your rate limit status
# Response headers include:
#   X-RateLimit-Limit: 1000
#   X-RateLimit-Remaining: 994
#   X-RateLimit-Reset: 1711843260

# Create a listing with a production key
curl -X POST https://mytradebuddy.com/api/listings.php \
  -H "Authorization: Bearer tb_live_sk_7f3a..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "School Blazer",
    "type": "Sell",
    "price": 25,
    "category": "School Uniform",
    "condition": "Good"
  }'
// Create a new API key
const key = await client.createApiKey({
  name: 'My Integration',
  type: 'secret',       // 'secret' | 'public'
  scopes: ['listings:read', 'listings:write'],
});
console.log(key.key); // "tb_live_sk_..." — shown once!

// List all your API keys
const keys = await client.listApiKeys();
keys.forEach(k => {
  console.log(k.name);       // "My Integration"
  console.log(k.lastUsed);   // "2026-03-28T14:30:00Z"
  console.log(k.requests);   // 4832
});

// Revoke a key
await client.revokeApiKey('key_abc123');

Available Scopes

listings:readView all marketplace listings
listings:writeCreate, update, and delete listings
users:readView user profiles
users:writeManage user accounts
webhooks:manageCreate and delete webhook subscriptions
analytics:readView usage statistics and metrics
Get Your API Keys

Embed
Embeddable Widget
Drop a single script tag on any website to display Trade Buddy listings. Customizable themes and filters.

Configure

HTML
<script
  src="https://tradebuddy.dev/widget.js"
  data-theme="dark"
  data-limit="5"
></script>

Live Preview

Graphing Calculator Electronics · Like New
$35
School Blazer School Uniform · Good
$25
Biology Textbook Books · Fair
$12
Tennis Racket Sports Equipment · Good
$18
Winter Jacket Clothing · Like New
Free

Command Line
Trade Buddy CLI
Browse listings, post items, and manage your account — all from the terminal.
  Terminal
~ npx tradebuddy

  Trade Buddy CLI v1.0.0
  Browse listings, post items, and manage your account.

  Quick start:
    $ tradebuddy login          Sign in to your account
    $ tradebuddy browse          Browse all listings
    $ tradebuddy browse -c Books Browse books only
    $ tradebuddy post            Post an item
    $ tradebuddy categories      List all 13 categories

  Run tradebuddy --help for all commands.

login / signup

Authenticate with your Trade Buddy account via interactive prompts.

browse

Search and filter listings by category, keyword, or type with -c and -s flags.

post

List products, donations, or wanted items with an interactive step-by-step flow.

categories

View all 13 marketplace categories at a glance.

$ npm install -g tradebuddy Click to copy
View on GitHub npm package

Roadmap
What we're building
Everything planned for the Trade Buddy developer platform.
Live

TypeScript SDK

Fully typed client for the Trade Buddy API. Install with npm, get autocomplete and type safety out of the box.

Live

Webhooks

Subscribe to real-time events — new listings, sales, account changes. Get HTTP POST notifications to your endpoint.

Live

Developer API Keys

Dedicated API keys for third-party apps. Rate limiting, usage analytics, and scoped permissions per key.

Live

Embeddable Widget

Drop a <script> tag on any school website to display Trade Buddy listings. Customizable themes and filters.

Live

CLI Tool

Interact with Trade Buddy from your terminal. Browse listings, post items, manage your account with npx tradebuddy.

Live

Quill

A beginner-friendly programming language that reads like English and compiles to JavaScript. quill.tradebuddy.dev

Planned

Status Page

Real-time API uptime monitoring at status.tradebuddy.dev. Incident history and response time metrics.

Planned

Changelog

Track every API change with versioned release notes. Never be surprised by breaking changes.


Architecture
What powers Trade Buddy
A full-stack architecture connecting parents across web and mobile with a shared database.

Website

Server-rendered PHP with MySQL. 12 category pages, admin panel, messaging, donations, wanted items.

PHPMySQLHTML/CSSJavaScript

Mobile App

Cross-platform React Native app built with Expo. Shares the same database and user accounts as the website.

React NativeExpoJavaScript

REST API

PHP endpoints with Bearer token auth. Powers the mobile app and the TypeScript SDK.

RESTJSONBearer Auth

Database

Shared MySQL database. Single source of truth for users, listings, messages, and sessions.

MySQLShared State

Discord Bot (Otter)

Multi-purpose TypeScript Discord bot for the Trade Buddy community server. Moderation, notifications, and more.

TypeScriptDiscord.jsNode.js
tradebuddyhq/site
Website, admin panel, and REST API.
PHPPrivate
tradebuddyhq/app
React Native mobile app. iOS and Android.
JavaScriptPublic
tradebuddyhq/sdk
Official TypeScript SDK. npm: @tradebuddy/sdk
TypeScriptPublic
tradebuddyhq/Otter
Multi-purpose Discord bot for the Trade Buddy server
TypeScriptPublic
tradebuddyhq/quill
Human-readable programming language. Compiles to JS.
GoPublic

Open Source
Contribute to Trade Buddy
Whether you're a student learning to code or an experienced developer, there's a place for you.
1

Fork the repo

Clone the app or SDK repository and set up your local dev environment.

git clone https://github.com/tradebuddyhq/app.git
2

Pick an issue

Check out open issues. Look for good first issue labels to get started.

gh issue list --repo tradebuddyhq/app
3

Submit a PR

Make your changes, test locally, and open a pull request. We review within 48 hours.

git checkout -b feature/your-feature

Team
Built by
The people behind Trade Buddy.
A

Arhan Harchandani

Founder & Developer

Projects
From Trade Buddy
Open source tools and languages by the Trade Buddy team.
New Project

Quill

A programming language for humans. Write code that reads like English — no cryptic syntax, no confusing errors. Compiles to JavaScript.

Try the Playground Documentation GitHub
hello.quill
-- A language anyone can read
name is "World"
say "Hello, {name}!"

colors are ["red", "green", "blue"]
for each color in colors:
  say "I like {color}"

to add a b:
  give back a + b

say add(10, 20)
40+built-in functions
REPLinteractive mode
Testingbuilt-in framework
Gocompiler
JSoutput target
tradebuddyhq/quill
A human-readable programming language that compiles to JavaScript. Compiler written in Go.
GoPublic
ebay-wrapper.js.org
eBay API wrapper for JavaScript and TypeScript. Simplifies eBay Browse, Finding, and Trading APIs.
JavaScriptOpen Source

Need help? Join our Discord

Get support with Quill, the SDK, and all Trade Buddy projects. Chat with the community and the dev team.

Join our Discord

Start building today

Install the SDK, explore the API, and help make school essentials accessible for every family.