API Architecture

The backend uses the FastAPI framework. It's organized into 10 router modules, which I'll discuss below. The main functionality is the API serves as a SPIN Sales Conversation Scorer that uses an LLM-powered assessment to analyze

API Endpoints by Category

1. Health & Monitoring (/health)

The typical health check endpoint to test out if the API works.

  • GET /health - Simple health check endpoint. Returns: { "ok": true}

2. Authentication (/auth)

Authentication uses PyJWT for token management, Passlib/bcrypt for password hashing, Pydantic for validation, and SQLAlchemy for database operations. Protected routes use the get_current_user dependency.

  • POST /auth/register - Register new user with organization
  • POST /auth/login - Login and get JWT token pair (access + refresh)
  • GET /auth/me - Get current authenticated user info
  • POST /auth/refresh - Refresh access token using refresh token
  • GET /auth/organizations - List active organizations (for registration)

3. Assessment/Scoring (/assess)

Authentication uses PyJWT for token management, Passlib/bcrypt for password hashing, Pydantic for validation, and SQLAlchemy for database operations. Protected routes use the get_current_user dependency.

  • POST /auth/register - Register new user with organization
  • POST /auth/login - Login and get JWT token pair (access + refresh)
  • GET /auth/me - Get current authenticated user info
  • POST /auth/refresh - Refresh access token using refresh token
  • GET /auth/organizations - List active organizations (for registration)

Code block

This is a block which you can put code in, that people can copy with one click! The code to make this work is in the sitewide body and head.

try {
function factorial(n) {
  if (n === 0 || n === 1) return 1;
  return n * factorial(n - 1);
}

// Array of numbers
const numbers = [1, 2, 3, 4, 5];

// Using map to create a new array with factorials
const factorials = numbers.map(factorial);

// Object with person details
const person = { name: "Alice", age: 30, city: "New York" };

// Destructuring object properties
const { name, age } = person;

console.log(`${name} is ${age} years old.`);
console.log(`Factorials: ${factorials.join(", ")}`);
}

Callouts

Use these callouts to share important information - you can use grey to show neutral important information, yellow to share warnings, red to share limitations, and green to emphasise positive information.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Accordions

Accordions are an excellent way to share information which only some people will need to read - that way, you aren't distracting people who don't need it. This is controlled by a Webflow interaction

Some niche topic

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

try {
function factorial(n) {
  if (n === 0 || n === 1) return 1;
  return n * factorial(n - 1);
}

Text formatting

You may need to indicate that a piece of text is to be used in code or an attribute. You can just add a styled span to indicate code.

Video block

I've not got much to say here - videos are great, and you should use them as much as possible to educate users on your product!

Image

A picture is worth a thousand words! Use images as much as possible to show your users what you're trying to explain!