New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@startsimpli/api

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@startsimpli/api

Type-safe Django REST API client for StartSimpli apps

latest
npmnpm
Version
0.5.5
Version published
Maintainers
1
Created
Source

@startsimpli/api

Type-safe Django REST API client for StartSimpli Next.js applications.

Overview

This package provides a type-safe TypeScript client for the Django REST API backend (start-simpli-api). It handles authentication, error normalization, pagination, and provides endpoint wrappers for all Django models.

IMPORTANT: This is a Django REST API client - NO Prisma, NO database code. All data lives in the Django backend.

Installation

npm install @startsimpli/api

Usage

Basic Setup

import { createStartSimpliApi } from '@startsimpli/api';

const api = createStartSimpliApi({
  baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1',
  getToken: async () => {
    // Get token from your auth provider
    const session = await getServerSession();
    return session?.accessToken || null;
  },
});

// Use API endpoints
const contacts = await api.contacts.list({ tier: 1 });
const orgs = await api.organizations.getByStage('seed');

Contacts API

// List contacts with filters
const contacts = await api.contacts.list(
  { tier: 1, has_linkedin: true }, // filters
  { page: 1, page_size: 20 },      // pagination
  { ordering: '-created_at' }       // sorting
);

// Get single contact
const contact = await api.contacts.get('contact-uuid');

// Create contact with assertions
const newContact = await api.contacts.create({
  name: 'John Doe',
  email: 'john@example.com',
  title: 'Partner',
  write_tags: ['tier_1', 'focus:fintech'],
  write_metrics: { enrichment_score: 0.95 },
  write_profiles: { linkedin: 'https://linkedin.com/in/johndoe' },
});

// Update contact
const updated = await api.contacts.update('contact-uuid', {
  title: 'Managing Partner',
  write_tags: ['tier_1', 'vip'],
});

// Search contacts
const results = await api.contacts.search('john');

// Get contacts by firm
const firmContacts = await api.contacts.getByFirm('firm-uuid');

Organizations API

// List organizations with filters
const orgs = await api.organizations.list(
  {
    tier: 1,
    stage: 'seed',
    check_size_min_gte: 100000,
    check_size_max_lte: 1000000,
  },
  { page: 1, page_size: 20 },
  { ordering: '-aum' }
);

// Get single organization
const org = await api.organizations.get('org-uuid');

// Create organization with assertions
const newOrg = await api.organizations.create({
  name: 'Acme Ventures',
  domain: 'acmevc.com',
  location: 'San Francisco, CA',
  write_tags: ['tier_1', 'stage:seed', 'focus:fintech'],
  write_metrics: {
    check_size_min: 500000,
    check_size_max: 2000000,
    aum: 100000000,
  },
  write_profiles: {
    linkedin: 'https://linkedin.com/company/acme-ventures',
    website: 'https://acmevc.com',
  },
});

// Get by check size range
const firms = await api.organizations.getByCheckSizeRange(100000, 1000000);

Entities API (Low-level)

// Tags
const tags = await api.entities.listTags();

// Entity Tags
const entityTags = await api.entities.listEntityTags(
  { page: 1, page_size: 50 },
  { entity_id: 'some-uuid', category: 'focus' }
);

// Metrics
const metrics = await api.entities.listMetrics(
  undefined,
  { entity_id: 'some-uuid', type: 'financial' }
);

// Profiles
const profiles = await api.entities.listProfiles(
  undefined,
  { entity_id: 'some-uuid', type: 'professional' }
);

Using Direct Client

For custom endpoints not covered by wrappers:

import { createApiClient } from '@startsimpli/api';

const client = createApiClient({
  baseUrl: 'http://localhost:8000/api/v1',
  getToken: async () => getAccessToken(),
});

// Direct fetch calls
const data = await client.fetch.get('/custom-endpoint/', {
  params: { key: 'value' }
});

const created = await client.fetch.post('/custom-endpoint/', {
  name: 'test'
});

Next.js API Routes Middleware

With Auth

import { withAuth } from '@startsimpli/api/middleware';

export const GET = withAuth(async (request, context) => {
  const { userId, token, isAuthenticated } = context;

  if (!isAuthenticated) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // Use token to call Django API
  return NextResponse.json({ userId, token });
});

With Validation

import { withValidation } from '@startsimpli/api/middleware';
import { z } from 'zod';

const createContactSchema = z.object({
  name: z.string().min(1),
  email: z.string().email().optional(),
  tier: z.number().int().min(1).max(3).optional(),
});

export const POST = withValidation(
  async (request, { body }) => {
    // body is typed and validated
    const contact = await createContact(body);
    return NextResponse.json(contact);
  },
  { body: createContactSchema }
);

With Error Handling

import { withErrorHandling } from '@startsimpli/api/middleware';

export const GET = withErrorHandling(async (request) => {
  // Errors are automatically caught and formatted
  const data = await somethingThatMightThrow();
  return NextResponse.json(data);
});

Composing Middleware

import { withAuth, withErrorHandling, withValidation } from '@startsimpli/api/middleware';
import { z } from 'zod';

const schema = z.object({ name: z.string() });

export const POST = withErrorHandling(
  withAuth(
    withValidation(
      async (request, { body }, authContext) => {
        // Fully typed, validated, and authenticated
        return NextResponse.json({ success: true });
      },
      { body: schema }
    )
  )
);

Error Handling

import {
  isApiException,
  isValidationError,
  isAuthError,
  isNotFoundError,
} from '@startsimpli/api';

try {
  const contact = await api.contacts.get('invalid-id');
} catch (error) {
  if (isValidationError(error)) {
    console.log('Validation errors:', error.errors);
  } else if (isAuthError(error)) {
    console.log('Auth error:', error.status);
  } else if (isNotFoundError(error)) {
    console.log('Contact not found');
  } else if (isApiException(error)) {
    console.log('API error:', error.message);
  }
}

TypeScript Types

All types are exported for use in your application:

import type {
  Contact,
  Organization,
  Entity,
  Tag,
  Metric,
  Profile,
  Attribute,
  PaginatedResponse,
  ApiError,
  CreateContactRequest,
  UpdateContactRequest,
  ContactFilters,
} from '@startsimpli/api';

Architecture

Django Integration

This package is designed to work with the Django REST API:

  • Base URL: http://localhost:8000/api/v1/ (configurable)
  • Auth: Bearer token from @startsimpli/auth
  • Pagination: Django REST Framework format (page, page_size)
  • Filtering: Django-filter query params (field__gte=100, field__in=1,2,3)

Entity System

Django uses a generic Entity model with assertions (Tags, Metrics, Profiles, Attributes):

// Entity with assertions
{
  id: 'uuid',
  entity_type: 'contact',

  // Canonical fields
  name: 'John Doe',
  email: 'john@example.com',

  // Computed from assertions
  tier: 1,  // from tags
  linkedin: 'https://...', // from profiles
  enrichment_score: 0.95, // from metrics

  // Full assertions
  tags: [{ category: 'quality', name: 'tier_1', ... }],
  metrics: [{ type: 'quality', subtype: 'enrichment_score', value: 0.95 }],
  profiles: [{ type: 'professional', subtype: 'linkedin', identifier: '...' }],
}

Development

# Run tests
npm test

# Type check
npm run type-check

License

MIT

FAQs

Package last updated on 02 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts