A standard request moves from submission to approval.
This is the normal reviewer path: create the request, validate it, approve it, and record the audit trail.
What this demonstrates
The API supports a normal business workflow with stable response shapes, explicit state transitions, and visible audit history.
Design tradeoff
I kept the contract narrow and stateful. The API surface is small, but the workflow rules stay explicit instead of hiding inside controller code.
Create approval request
POST /approval-requestsRequest
{
"title": "Renew analytics workspace seats",
"amount": 1200,
"currency": "CAD",
"costCenter": "CC-2040",
"justification": "Keeps the delivery team on the supported analytics environment.",
"requesterId": "u-requester"
} Response
{
"ok": true,
"status": 201,
"body": {
"request": {
"requestId": "APR-1001",
"title": "Renew analytics workspace seats",
"amount": 1200,
"currency": "CAD",
"costCenter": "CC-2040",
"justification": "Keeps the delivery team on the supported analytics environment.",
"requesterId": "u-requester",
"requiredApprovalRole": "manager",
"state": "pending",
"approvedBy": null,
"auditTrail": [
{
"type": "request_created",
"actorId": "u-requester",
"at": "2026-05-15T09:00:00Z",
"note": "Request submitted for review"
}
]
}
}
} Approve request
POST /approval-requests/APR-1001/approveRequest
{
"actorId": "u-manager",
"role": "manager"
} Response
{
"ok": true,
"status": 200,
"body": {
"request": {
"requestId": "APR-1001",
"title": "Renew analytics workspace seats",
"amount": 1200,
"currency": "CAD",
"costCenter": "CC-2040",
"justification": "Keeps the delivery team on the supported analytics environment.",
"requesterId": "u-requester",
"requiredApprovalRole": "manager",
"state": "approved",
"approvedBy": "u-manager",
"auditTrail": [
{
"type": "request_created",
"actorId": "u-requester",
"at": "2026-05-15T09:00:00Z",
"note": "Request submitted for review"
},
{
"type": "request_approved",
"actorId": "u-manager",
"at": "2026-05-15T09:05:00Z",
"note": "Approved by manager"
}
]
}
}
} Code path
Implementation excerpt
export const approveRequest = (
request: ApprovalRequest,
actor: Actor,
options?: { now?: string }
): ApiResult<{ request: ApprovalRequest }> => {
if (actor.role !== "manager" && actor.role !== "finance") {
return {
ok: false,
status: 403,
body: {
error: {
code: "approval_role_required",
message: "Only manager or finance reviewers can approve requests."
}
}
};
}
if (request.state !== "pending") {
return {
ok: false,
status: 409,
body: {
error: {
code: "request_not_pending",
message: "Only pending requests can move to approval."
}
}
};
}
if (actor.userId === request.requesterId) {
return {
ok: false,
status: 409,
body: {
error: {
code: "separation_of_duties_required",
message: "The requester cannot approve their own request."
}
}
};
}
if (request.requiredApprovalRole === "finance" && actor.role !== "finance") {
return {
ok: false,
status: 422,
body: {
error: {
code: "finance_review_required",
message: "Requests above the manager approval limit must be approved by finance.",
nextAction: "Route the request to a finance reviewer."
}
}
};
}
return {
ok: true,
status: 200,
body: {
request: appendAuditEvent(
{
...request,
state: "approved",
approvedBy: actor.userId
},
{
type: "request_approved",
actorId: actor.userId,
at: options?.now,
note: `Approved by ${actor.role}`
}
)
}
};
}; Show the full workflow module
export type ApprovalState = "pending" | "approved" | "rejected";
export type ApprovalRole = "requester" | "manager" | "finance";
export interface ApprovalRequestInput {
title: string;
amount: number;
currency: "CAD" | "USD";
costCenter: string;
justification: string;
requesterId: string;
}
export interface Actor {
userId: string;
role: ApprovalRole;
}
export interface AuditEvent {
type: "request_created" | "request_approved" | "request_rejected";
actorId: string;
at: string;
note: string;
}
export interface ApprovalRequest {
requestId: string;
title: string;
amount: number;
currency: "CAD" | "USD";
costCenter: string;
justification: string;
requesterId: string;
requiredApprovalRole: "manager" | "finance";
state: ApprovalState;
approvedBy: string | null;
auditTrail: AuditEvent[];
}
export interface ApiErrorBody {
error: {
code: string;
message: string;
details?: string[];
nextAction?: string;
};
}
export type ApiResult<T> =
| {
ok: true;
status: number;
body: T;
}
| {
ok: false;
status: number;
body: ApiErrorBody;
};
const MANAGER_LIMIT = 2500;
const validationErrors = (input: ApprovalRequestInput) => {
const errors: string[] = [];
if (input.title.trim().length < 8) {
errors.push("title must be at least 8 characters");
}
if (input.amount <= 0) {
errors.push("amount must be greater than zero");
}
if (input.justification.trim().length < 20) {
errors.push("justification must be at least 20 characters");
}
if (!/^CC-[0-9]{4}$/u.test(input.costCenter)) {
errors.push("costCenter must use the CC-0000 format");
}
return errors;
};
const appendAuditEvent = (
request: ApprovalRequest,
event: Omit<AuditEvent, "at"> & { at?: string }
): ApprovalRequest => ({
...request,
auditTrail: [
...request.auditTrail,
{
...event,
at: event.at ?? new Date().toISOString()
}
]
});
// snippet:create-request-start
export const createApprovalRequest = (
input: ApprovalRequestInput,
options?: { requestId?: string; now?: string }
): ApiResult<{ request: ApprovalRequest }> => {
const errors = validationErrors(input);
if (errors.length > 0) {
return {
ok: false,
status: 422,
body: {
error: {
code: "validation_failed",
message: "The request payload did not pass workflow validation.",
details: errors
}
}
};
}
const request: ApprovalRequest = {
requestId: options?.requestId ?? "APR-1001",
title: input.title,
amount: input.amount,
currency: input.currency,
costCenter: input.costCenter,
justification: input.justification,
requesterId: input.requesterId,
requiredApprovalRole: input.amount > MANAGER_LIMIT ? "finance" : "manager",
state: "pending",
approvedBy: null,
auditTrail: []
};
return {
ok: true,
status: 201,
body: {
request: appendAuditEvent(request, {
type: "request_created",
actorId: input.requesterId,
at: options?.now,
note: "Request submitted for review"
})
}
};
};
// snippet:create-request-end
// snippet:approve-request-start
export const approveRequest = (
request: ApprovalRequest,
actor: Actor,
options?: { now?: string }
): ApiResult<{ request: ApprovalRequest }> => {
if (actor.role !== "manager" && actor.role !== "finance") {
return {
ok: false,
status: 403,
body: {
error: {
code: "approval_role_required",
message: "Only manager or finance reviewers can approve requests."
}
}
};
}
if (request.state !== "pending") {
return {
ok: false,
status: 409,
body: {
error: {
code: "request_not_pending",
message: "Only pending requests can move to approval."
}
}
};
}
if (actor.userId === request.requesterId) {
return {
ok: false,
status: 409,
body: {
error: {
code: "separation_of_duties_required",
message: "The requester cannot approve their own request."
}
}
};
}
if (request.requiredApprovalRole === "finance" && actor.role !== "finance") {
return {
ok: false,
status: 422,
body: {
error: {
code: "finance_review_required",
message: "Requests above the manager approval limit must be approved by finance.",
nextAction: "Route the request to a finance reviewer."
}
}
};
}
return {
ok: true,
status: 200,
body: {
request: appendAuditEvent(
{
...request,
state: "approved",
approvedBy: actor.userId
},
{
type: "request_approved",
actorId: actor.userId,
at: options?.now,
note: `Approved by ${actor.role}`
}
)
}
};
};
// snippet:approve-request-end
export const rejectRequest = (
request: ApprovalRequest,
actor: Actor,
reason: string,
options?: { now?: string }
): ApiResult<{ request: ApprovalRequest }> => {
if (request.state !== "pending") {
return {
ok: false,
status: 409,
body: {
error: {
code: "request_not_pending",
message: "Only pending requests can be rejected."
}
}
};
}
if (actor.role !== "manager" && actor.role !== "finance") {
return {
ok: false,
status: 403,
body: {
error: {
code: "approval_role_required",
message: "Only manager or finance reviewers can reject requests."
}
}
};
}
return {
ok: true,
status: 200,
body: {
request: appendAuditEvent(
{
...request,
state: "rejected"
},
{
type: "request_rejected",
actorId: actor.userId,
at: options?.now,
note: reason
}
)
}
};
}; Test coverage
Test mapped to this scenario
it("approves a standard request with manager review", () => {
const created = createApprovalRequest(
{
title: "Renew analytics workspace seats",
amount: 1200,
currency: "CAD",
costCenter: "CC-2040",
justification: "Keeps the delivery team on the supported analytics environment.",
requesterId: "u-requester"
},
{ requestId: "APR-1001", now: "2026-05-15T09:00:00Z" }
);
expect(created.ok).toBe(true);
if (!created.ok) {
throw new Error("expected create request to succeed");
}
const approved = approveRequest(created.body.request, { userId: "u-manager", role: "manager" }, {
now: "2026-05-15T09:05:00Z"
});
expect(approved.ok).toBe(true);
if (!approved.ok) {
throw new Error("expected approval to succeed");
}
expect(approved.body.request.state).toBe("approved");
expect(approved.body.request.approvedBy).toBe("u-manager");
expect(approved.body.request.auditTrail).toHaveLength(2);
}); Show the full test file
import { describe, expect, it } from "vitest";
import { approveRequest, createApprovalRequest, rejectRequest } from "./engine";
// snippet:test-happy-path-start
it("approves a standard request with manager review", () => {
const created = createApprovalRequest(
{
title: "Renew analytics workspace seats",
amount: 1200,
currency: "CAD",
costCenter: "CC-2040",
justification: "Keeps the delivery team on the supported analytics environment.",
requesterId: "u-requester"
},
{ requestId: "APR-1001", now: "2026-05-15T09:00:00Z" }
);
expect(created.ok).toBe(true);
if (!created.ok) {
throw new Error("expected create request to succeed");
}
const approved = approveRequest(created.body.request, { userId: "u-manager", role: "manager" }, {
now: "2026-05-15T09:05:00Z"
});
expect(approved.ok).toBe(true);
if (!approved.ok) {
throw new Error("expected approval to succeed");
}
expect(approved.body.request.state).toBe("approved");
expect(approved.body.request.approvedBy).toBe("u-manager");
expect(approved.body.request.auditTrail).toHaveLength(2);
});
// snippet:test-happy-path-end
// snippet:test-finance-rule-start
it("requires finance review for requests above the manager limit", () => {
const created = createApprovalRequest(
{
title: "Approve year-end disaster recovery rehearsal",
amount: 8600,
currency: "CAD",
costCenter: "CC-2040",
justification: "Covers the annual rehearsal with contracted vendor and overtime support.",
requesterId: "u-requester"
},
{ requestId: "APR-1002", now: "2026-05-15T11:00:00Z" }
);
if (!created.ok) {
throw new Error("expected create request to succeed");
}
const result = approveRequest(created.body.request, { userId: "u-manager", role: "manager" }, {
now: "2026-05-15T11:05:00Z"
});
expect(result.ok).toBe(false);
if (result.ok) {
throw new Error("expected finance rule to reject manager approval");
}
expect(result.status).toBe(422);
expect(result.body.error.code).toBe("finance_review_required");
});
// snippet:test-finance-rule-end
// snippet:test-unauthorized-start
it("blocks actors without approval permissions", () => {
const created = createApprovalRequest(
{
title: "Renew staging monitoring coverage",
amount: 640,
currency: "CAD",
costCenter: "CC-2040",
justification: "Maintains non-production monitoring before the next release cycle.",
requesterId: "u-requester"
},
{ requestId: "APR-1003", now: "2026-05-15T13:00:00Z" }
);
if (!created.ok) {
throw new Error("expected create request to succeed");
}
const result = approveRequest(created.body.request, { userId: "u-contractor", role: "requester" }, {
now: "2026-05-15T13:04:00Z"
});
expect(result.ok).toBe(false);
if (result.ok) {
throw new Error("expected approval permissions check to fail");
}
expect(result.status).toBe(403);
expect(result.body.error.code).toBe("approval_role_required");
});
// snippet:test-unauthorized-end
describe("approval workflow extra checks", () => {
it("rejects invalid create payloads", () => {
const created = createApprovalRequest(
{
title: "Short",
amount: 0,
currency: "CAD",
costCenter: "2040",
justification: "Too short",
requesterId: "u-requester"
},
{ requestId: "APR-2001", now: "2026-05-15T14:00:00Z" }
);
expect(created.ok).toBe(false);
if (created.ok) {
throw new Error("expected validation to fail");
}
expect(created.status).toBe(422);
expect(created.body.error.details).toContain("amount must be greater than zero");
});
it("records rejection decisions with an audit note", () => {
const created = createApprovalRequest(
{
title: "Backfill release support coverage",
amount: 900,
currency: "CAD",
costCenter: "CC-2040",
justification: "Covers release support while a teammate is on approved leave.",
requesterId: "u-requester"
},
{ requestId: "APR-2002", now: "2026-05-15T15:00:00Z" }
);
if (!created.ok) {
throw new Error("expected create request to succeed");
}
const rejected = rejectRequest(
created.body.request,
{ userId: "u-manager", role: "manager" },
"Budget freeze for the current sprint window.",
{ now: "2026-05-15T15:10:00Z" }
);
expect(rejected.ok).toBe(true);
if (!rejected.ok) {
throw new Error("expected rejection to succeed");
}
expect(rejected.body.request.state).toBe("rejected");
expect(rejected.body.request.auditTrail.at(-1)?.note).toContain("Budget freeze");
});
});