Skip to content

About

Demo app for Every.org

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Every.org Software Engineer Coding Challenge: Donation Processor

Every.org processes millions of dollars in donations for thousands of nonprofits. Once in a blue moon, a donation has to be processed manually. Using any tools and languages at your disposal, your task is to build a simple internal tool for processing and managing donations.

Getting started

Prerequisites

  • Node.js 22 or later
  • npm 10 or later (bundled with Node 22)

Install

npm install

Run

npm run dev

This starts both servers concurrently:

Service URL
API http://localhost:3001
Dashboard http://localhost:5173

Database

The SQLite database (api/donations.db) is not committed to the repo. On first run it is created automatically and seeded with the eight sample donations from sample.json — no setup required.

To reset and re-seed (wipes all data and restores the sample donations on next start):

npm run db:reset
npm run dev

To start with an empty database (useful for testing POST /donations from scratch):

SEED=false npm run dev

Original brief

What you'll build

A full stack application with:

  1. A backend API that ingests and processes donations
  2. An internal dashboard UI for viewing and updating donation statuses

As a reminder, you have 2 hours to complete this, with a grace period of 1 additional hour. AI use is allowed and encouraged. Best of luck!


Data Model

Use the following TypeScript interfaces as your data model:

type PaymentMethod = "cc" | "ach" | "crypto" | "venmo";
type DonationStatus = "new" | "pending" | "success" | "failure";
interface Donation {
	uuid: string; // unique identifier
	amount: number; // in cents, e.g. 5000 = $50.00
	currency: "USD";
	paymentMethod: PaymentMethod;
	nonprofitId: string;
	donorId: string;
	status: DonationStatus;
	createdAt: string; // ISO datetime string
	updatedAt: string; // ISO datetime string
}

API Contract

POST /donations Ingest and process a new donation.

Request body:

{
	uuid: string;
	amount: number;
	currency: "USD";
	paymentMethod: PaymentMethod;
	nonprofitId: string;
	donorId: string;
	status: DonationStatus;
	createdAt: string;
}

Responses:

  • 201 : donation successfully created
  • 409 : conflict (see idempotency note in Backend Requirements)
  • 400 : invalid payload

GET /donations Retrieve all donations.

Response:

{
	donations: Donation[];
}

GET /donations/:uuid Retrieve a single donation by UUID.

Responses:

  • 200 : donation found
  • 404 : donation not found

PATCH /donations/:uuid/status Update the status of a donation.

Request body:

{
	status: DonationStatus;
}

Responses:

  • 200 : status successfully updated
  • 409 : conflict (see idempotency note in Backend Requirements)
  • 422 : invalid status transition
  • 404 : donation not found

Status Transitions

Valid transitions are:

new → pending
pending → success
pending → failure

Any other transition must be rejected with a 422 and a clear error message. For example:

  • new → success ❌
  • failure → pending ❌
  • success → failure ❌

Sample Data

Seed your database or in-memory store with sample donations


Backend Requirements

Original brief: At minimum, a PATCH request where the target status is identical to the current status should return a 409. Beyond that, the interpretation of what constitutes a duplicate status update request is intentionally underspecified. Choose an approach that makes sense to you and document your reasoning in the README.

For POST: 409 if a donation with the same UUID already exists.

For PATCH: 409 if the requested status equals the current status (the required minimum). A retry with a valid forward transition (e.g. retrying new → pending after network failure) succeeds if the transition is still valid, or 409 if the transition already applied.


UI Requirements

Build a dashboard that allows internal users to:

  • View all donations with their current status, amount, payment method, and nonprofit
  • Update the status of a donation using the valid transitions above The UI requirements are intentionally minimal. Use your own judgment to decide what an operator would actually need and document any product decisions you made in your README.

What good UI judgment looks like:

  • Invalid transitions are not offered to the user (e.g. a success donation has no further actions)
  • Errors from the API are surfaced clearly
  • Amounts are displayed in dollars, not cents

The UI does not need to be polished; clarity and correctness matter more than aesthetics.


Optional Extensions

If you finish early, consider adding one of the following or something of your own choosing:

  • Filtering donations by status or payment method
  • A summary view (e.g. total donated by payment method, success/failure rate)
  • Webhook simulation: emit an event when a donation reaches success or failure
  • Anything else you think makes this more production-ready

About

Demo app for Every.org

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages