Backend

API Reference

Backend API endpoints and integration guide

Base URL

http://localhost:8000/api/v1

Authentication

The API uses Clerk JWT tokens for authentication. Include the token in the Authorization header:

Authorization: Bearer <jwt-token>

Endpoints

Importers

List Importers

Get all importers for the authenticated user.

GET /importers

Query parameters:

  • skip: Number of records to skip (default: 0)
  • limit: Maximum records to return (default: 100)

Response:

[
  {
    "id": "uuid",
    "name": "Customer Import",
    "key": "uuid-key-string",
    "description": "Import customer data",
    "fields": [...],
    "webhook_url": "https://example.com/webhook",
    "webhook_enabled": true,
    "include_data_in_webhook": false,
    "webhook_data_sample_size": 10,
    "include_unmatched_columns": false,
    "filter_invalid_rows": false,
    "disable_on_invalid_rows": false,
    "dark_mode": false,
    "created_at": "2024-01-01T00:00:00Z"
  }
]

Get Importer

Get a specific importer by ID.

GET /importers/{importer_id}

Response:

{
  "id": "uuid",
  "name": "Customer Import",
  "key": "uuid-key-string",
  "description": "Import customer data",
  "fields": [
    {
      "name": "email",
      "display_name": "Email Address",
      "id": "email",              // Computed from name
      "label": "Email Address",    // Computed from display_name
      "type": "email",
      "validators": [
        {
          "type": "required",
          "message": "Email is required"
        }
      ],
      "transformations": [
        { "type": "trim" },
        { "type": "lowercase" }
      ],
      "options": null
    }
  ],
  "webhook_url": "https://example.com/webhook",
  "webhook_enabled": true,
  "include_data_in_webhook": false,
  "webhook_data_sample_size": 10,
  "include_unmatched_columns": false,
  "filter_invalid_rows": false,
  "disable_on_invalid_rows": false,
  "dark_mode": false,
  "created_at": "2024-01-01T00:00:00Z",
  "updated_at": "2024-01-01T00:00:00Z"
}

Create Importer

Create a new importer configuration.

POST /importers

Request body:

{
  "name": "Customer Import",
  "description": "Import customer data",
  "fields": [
    {
      "name": "email",
      "display_name": "Email Address",
      "type": "email",
      "validators": [
        {
          "type": "required",
          "message": "Email is required"
        }
      ],
      "transformations": [
        { "type": "trim" },
        { "type": "lowercase" }
      ],
      "options": null
    }
  ],
  "webhook_url": "https://example.com/webhook",
  "webhook_enabled": true,
  "include_data_in_webhook": false,
  "webhook_data_sample_size": 10,
  "include_unmatched_columns": false,
  "filter_invalid_rows": false,
  "disable_on_invalid_rows": false,
  "dark_mode": false
}

Response: Returns the created importer object with generated ID and key.

Update Importer

Update an existing importer configuration.

PUT /importers/{importer_id}

Request body: Same as create, all fields optional.

Delete Importer

Delete an importer configuration.

DELETE /importers/{importer_id}

Response: 204 No Content

Imports

Create Import

Start a new import job.

POST /imports

Request body (multipart/form-data):

  • file: CSV/Excel file
  • importer_id: UUID of the importer
  • mapping: JSON object mapping CSV columns to importer fields

Example mapping:

{
  "CSV Column Name": "email",
  "Customer Name": "name"
}

Response:

{
  "id": "uuid",
  "importer_id": "uuid",
  "status": "processing",
  "created_at": "2024-01-01T00:00:00Z"
}

Get Import Status

Check the status of an import job.

GET /imports/{import_id}

Response:

{
  "id": "uuid",
  "importer_id": "uuid",
  "status": "completed",
  "num_rows": 100,
  "num_errors": 2,
  "errors": [
    {
      "row": 5,
      "field": "email",
      "message": "Invalid email format"
    }
  ],
  "created_at": "2024-01-01T00:00:00Z",
  "completed_at": "2024-01-01T00:01:00Z"
}

Status values:

  • pending: Job queued
  • processing: Currently processing
  • completed: Successfully completed
  • failed: Processing failed

Clerk Webhook

User Sync

Endpoint for Clerk webhook events (user creation, updates, deletion).

POST /clerk/webhook

Headers:

  • svix-id: Webhook event ID
  • svix-timestamp: Event timestamp
  • svix-signature: Webhook signature for verification

This endpoint is automatically called by Clerk and should not be manually invoked.

Field Types

Supported field types for importer configuration:

  • text: General text input
  • email: Email validation
  • number: Numeric values
  • date: Date fields
  • phone: Phone number fields
  • boolean: Boolean values
  • select: Dropdown with options
  • custom_regex: Custom regex validation

Field Schema

Each field in the importer configuration has this structure:

{
  "name": "field_id",              // Required: unique identifier
  "display_name": "Field Label",   // Optional: human-readable name
  "type": "text",                  // Required: field type
  "validators": [...],              // Optional: validation rules
  "transformations": [...],         // Optional: data transformations
  "options": [...]                  // Optional: for select type
}

Note: The backend automatically computes:

  • id property from name (for Column format compatibility)
  • label property from display_name or auto-generates from name

Validators

Available validation rules:

Required

{
  "type": "required",
  "message": "Field is required"
}

Min/Max Length (for strings)

{
  "type": "min_length",
  "value": 3,
  "message": "Minimum 3 characters"
}
{
  "type": "max_length",
  "value": 50,
  "message": "Maximum 50 characters"
}

Min/Max Value (for numbers)

{
  "type": "min",
  "value": 0,
  "message": "Must be positive"
}
{
  "type": "max",
  "value": 100,
  "message": "Must be 100 or less"
}

Regex Pattern

{
  "type": "regex",
  "pattern": "^[A-Z]{2}\\d{4}$",
  "message": "Invalid format"
}

Unique

{
  "type": "unique",
  "message": "Duplicate value found"
}

Transformations

Available data transformations:

{
  "transformations": [
    { "type": "trim" },
    { "type": "uppercase" },
    { "type": "lowercase" },
    { "type": "capitalize" },
    { "type": "remove_special_chars" },
    { "type": "normalize_phone" },
    { "type": "normalize_date", "format": "YYYY-MM-DD" },
    { "type": "default", "value": "N/A" },
    { "type": "replace", "find": " ", "replace": "_" }
  ]
}

Transformation types:

  • trim: Remove leading/trailing whitespace
  • uppercase: Convert to UPPERCASE
  • lowercase: Convert to lowercase
  • capitalize: Capitalize First Letter Of Each Word
  • remove_special_chars: Keep only alphanumeric and spaces
  • normalize_phone: Format phone numbers (US format)
  • normalize_date: Parse and format dates
  • default: Replace empty values with default
  • replace: Find and replace strings

Webhook Events

When webhook is enabled, the following events are sent:

Import Started

{
  "event": "import.started",
  "importer_id": "uuid",
  "import_id": "uuid",
  "timestamp": "2024-01-01T00:00:00Z"
}

Import Completed

{
  "event": "import.completed",
  "importer_id": "uuid",
  "import_id": "uuid",
  "num_rows": 100,
  "timestamp": "2024-01-01T00:00:00Z"
}

Import Failed

{
  "event": "import.failed",
  "importer_id": "uuid",
  "import_id": "uuid",
  "error": "Processing error",
  "timestamp": "2024-01-01T00:00:00Z"
}

Importer Configuration Options

Additional configuration options for importers:

FieldTypeDefaultDescription
include_unmatched_columnsbooleanfalseInclude CSV columns not defined in schema
filter_invalid_rowsbooleanfalseFilter out rows that fail validation
disable_on_invalid_rowsbooleanfalsePrevent import if any row has errors
include_data_in_webhookbooleanfalseInclude processed data in webhook payload
webhook_data_sample_sizenumbernullNumber of rows to include in webhook sample
dark_modebooleanfalseEnable dark mode for the importer UI

Invalid Row Handling

Control how the importer handles validation errors:

  • disable_on_invalid_rows: true: Blocks import if ANY row has errors (strictest)
  • filter_invalid_rows: true: Filters out invalid rows, imports only valid ones
  • Neither set: Imports all rows with warnings for invalid ones (most permissive)

Error Responses

Standard error format:

{
  "detail": "Error message",
  "status_code": 400
}

Common status codes:

  • 400: Bad Request
  • 401: Unauthorized
  • 403: Forbidden
  • 404: Not Found
  • 422: Validation Error
  • 500: Internal Server Error