InfraForge Docs

InfraNotes CORE · v1.35.9

Welcome

Select a document from the sidebar to read it.

InfraNotes Client System - Frontend Implementation Guide

This guide provides detailed information on how to integrate with the InfraNotes client system API. It includes all available endpoints, their request/response formats, and examples.

Table of Contents

  1. Authentication
  2. Client Operations
  3. Contact Person Operations
  4. Custom Fields

Authentication

All API endpoints require authentication using JWT Bearer tokens. Include the token in the Authorization header:

Authorization: Bearer your_jwt_token

Client Operations

Create Client

Endpoint: POST /api/clients

Request Body:

{
  "type": "client",
  "category": "organization",
  "name": "Example Organization",
  "contact_name": "Primary Contact",
  "email": "contact@example.com",
  "phone": "+1234567890",
  "address": "123 Main St",
  "city": "New York",
  "state": "NY",
  "postal_code": "10001",
  "country": "USA",
  "tax_number": "TAX12345",
  "company_registration_number": "REG98765",
  "notes": "Client notes",
  "website": "https://example.com",
  "default_currency": "USD",
  "payment_terms_id": 1,
  "bank_name": "Example Bank",
  "account_name": "Example Account",
  "account_number": "123456789",
  "iban": "US12345678901234567890",
  "swift": "EXAMPLESWIFT",
  "custom_fields": {
    "Industry": "Technology",
    "Size": "Enterprise"
  },
  "categories": ["Category1", "Category2"],
  "tags": ["Tag1", "Tag2"]
}

For an individual client, use:

{
  "type": "client",
  "category": "individual",
  "name": "John Smith",
  "contact_name": "John Smith",
  "email": "john@example.com",
  "phone": "+1234567890",
  "address": "123 Main St",
  "city": "New York",
  "state": "NY",
  "postal_code": "10001",
  "country": "USA",
  "tax_number": "TAX12345",
  "notes": "Individual client notes",
  "website": "https://johnsmith.com",
  "default_currency": "USD",
  "payment_terms_id": 1,
  "bank_name": "Example Bank",
  "account_name": "John Smith",
  "account_number": "123456789",
  "iban": "US12345678901234567890",
  "swift": "EXAMPLESWIFT",
  "custom_fields": {
    "Occupation": "Consultant",
    "Referral": "Website"
  }
}

Response: The created client with ID and timestamp fields.

{
  "id": 1,
  "type": "client",
  "category": "organization",
  "name": "Example Organization",
  "contact_name": "Primary Contact",
  "email": "contact@example.com",
  "phone": "+1234567890",
  "address": "123 Main St",
  "city": "New York",
  "state": "NY",
  "postal_code": "10001",
  "country": "USA",
  "tax_number": "TAX12345",
  "company_registration_number": "REG98765",
  "notes": "Client notes",
  "website": "https://example.com",
  "default_currency": "USD",
  "user_id": 2,
  "payment_terms_id": 1,
  "bank_name": "Example Bank",
  "account_name": "Example Account",
  "account_number": "123456789",
  "iban": "US12345678901234567890",
  "swift": "EXAMPLESWIFT",
  "custom_fields": {
    "Industry": "Technology",
    "Size": "Enterprise"
  },
  "categories": ["Category1", "Category2"],
  "tags": ["Tag1", "Tag2"],
  "created_at": "2025-05-22T16:45:23.123456Z",
  "updated_at": "2025-05-22T16:45:23.123456Z"
}

Get Client

Endpoint: GET /api/clients/{id}

Parameters:

  • id (path parameter): Client ID

Response: Complete client details including contacts.

{
  "id": 1,
  "type": "client",
  "category": "organization",
  "name": "Example Organization",
  "contact_name": "Primary Contact",
  "email": "contact@example.com",
  "phone": "+1234567890",
  "address": "123 Main St",
  "city": "New York",
  "state": "NY",
  "postal_code": "10001",
  "country": "USA",
  "tax_number": "TAX12345",
  "company_registration_number": "REG98765",
  "notes": "Client notes",
  "website": "https://example.com",
  "default_currency": "USD",
  "user_id": 2,
  "payment_terms_id": 1,
  "bank_name": "Example Bank",
  "account_name": "Example Account",
  "account_number": "123456789",
  "iban": "US12345678901234567890",
  "swift": "EXAMPLESWIFT",
  "custom_fields": {
    "Industry": "Technology",
    "Size": "Enterprise"
  },
  "categories": ["Category1", "Category2"],
  "tags": ["Tag1", "Tag2"],
  "contacts": [
    {
      "id": 1,
      "client_id": 1,
      "name": "John Doe",
      "position": "CEO",
      "email": "john@example.com",
      "phone": "+1987654321",
      "is_primary": true,
      "created_at": "2025-05-22T16:45:23.123456Z",
      "updated_at": "2025-05-22T16:45:23.123456Z"
    },
    {
      "id": 2,
      "client_id": 1,
      "name": "Jane Smith",
      "position": "CFO",
      "email": "jane@example.com",
      "phone": "+1122334455",
      "is_primary": false,
      "created_at": "2025-05-22T16:45:23.123456Z",
      "updated_at": "2025-05-22T16:45:23.123456Z"
    }
  ],
  "created_at": "2025-05-22T16:45:23.123456Z",
  "updated_at": "2025-05-22T16:45:23.123456Z"
}

Update Client

Endpoint: PUT /api/clients/{id}

Parameters:

  • id (path parameter): Client ID

Request Body: Same as create client with fields to update.

Response: The updated client.

Delete Client

Endpoint: DELETE /api/clients/{id}

Parameters:

  • id (path parameter): Client ID

Response: Success message.

List Clients

Endpoint: GET /api/clients

Query Parameters:

  • type (optional): Filter by type (client or vendor)
  • category (optional): Filter by category (individual or organization)
  • country (optional): Filter by country
  • category (optional): Filter by assigned category
  • tag (optional): Filter by assigned tag
  • limit (optional): Number of results (default 50)
  • offset (optional): Pagination offset

Response: List of clients matching the filters.

Search Clients

Endpoint: GET /api/clients/search

Query Parameters:

  • query (required): Search term
  • limit (optional): Maximum number of results to return (default 10)

Response: List of clients matching the search term.

Contact Person Operations

Add Contact Person

Endpoint: POST /api/clients/{client_id}/contacts

Parameters:

  • client_id (path parameter): Client ID

Request Body:

{
  "name": "John Doe",
  "position": "CEO",
  "email": "john@example.com",
  "phone": "+1987654321",
  "is_primary": true
}

Response: The created contact person.

{
  "id": 1,
  "client_id": 1,
  "name": "John Doe",
  "position": "CEO",
  "email": "john@example.com",
  "phone": "+1987654321",
  "is_primary": true,
  "created_at": "2025-05-22T16:45:23.123456Z",
  "updated_at": "2025-05-22T16:45:23.123456Z"
}

Get Contact Person

Endpoint: GET /api/contacts/{id}

Parameters:

  • id (path parameter): Contact Person ID

Response: The contact person details.

Update Contact Person

Endpoint: PUT /api/contacts/{id}

Parameters:

  • id (path parameter): Contact Person ID

Request Body:

{
  "name": "John Doe",
  "position": "CTO",
  "email": "john.doe@example.com",
  "phone": "+1987654321",
  "is_primary": true
}

Response: The updated contact person.

Delete Contact Person

Endpoint: DELETE /api/contacts/{id}

Parameters:

  • id (path parameter): Contact Person ID

Response: Success message.

Set Primary Contact

Endpoint: PUT /api/contacts/{id}/primary

Parameters:

  • id (path parameter): Contact Person ID

Response: The updated contact person with is_primary set to true.

List Contact Persons

Endpoint: GET /api/clients/{client_id}/contacts

Parameters:

  • client_id (path parameter): Client ID

Response: List of contact persons for the client.

[
  {
    "id": 1,
    "client_id": 1,
    "name": "John Doe",
    "position": "CEO",
    "email": "john@example.com",
    "phone": "+1987654321",
    "is_primary": true,
    "created_at": "2025-05-22T16:45:23.123456Z",
    "updated_at": "2025-05-22T16:45:23.123456Z"
  },
  {
    "id": 2,
    "client_id": 1,
    "name": "Jane Smith",
    "position": "CFO",
    "email": "jane@example.com",
    "phone": "+1122334455",
    "is_primary": false,
    "created_at": "2025-05-22T16:45:23.123456Z",
    "updated_at": "2025-05-22T16:45:23.123456Z"
  }
]

Custom Fields

Create Custom Field

Endpoint: POST /api/custom-fields

Request Body:

For a simple text field:

{
  "name": "Industry",
  "type": "text",
  "entity": "client",
  "required": false,
  "default_value": "",
  "placeholder": "Enter industry",
  "display_order": 1
}

For a numeric field:

{
  "name": "Annual Revenue",
  "type": "number",
  "entity": "client",
  "required": false,
  "default_value": "",
  "placeholder": "Enter annual revenue",
  "display_order": 2
}

For a dropdown field with options:

{
  "name": "Client Priority",
  "type": "dropdown",
  "entity": "client",
  "required": true,
  "options": ["Low", "Medium", "High", "Critical"],
  "default_value": "Medium",
  "display_order": 3
}

Valid types: text, number, date, dropdown, checkbox
Valid entities: client, invoice, expense, project

Response: The created custom field.

{
  "id": 1,
  "name": "Industry",
  "type": "text",
  "entity": "client",
  "required": false,
  "default_value": "",
  "placeholder": "Enter industry",
  "user_id": 2,
  "display_order": 1,
  "created_at": "2025-05-22T16:45:23.123456Z",
  "updated_at": "2025-05-22T16:45:23.123456Z"
}

Get Custom Fields

Endpoint: GET /api/custom-fields/{entity}

Parameters:

  • entity (path parameter): Entity type (client, invoice, expense, project)

Response: List of custom fields for the specified entity.

[
  {
    "id": 1,
    "name": "Industry",
    "type": "text",
    "entity": "client",
    "required": false,
    "default_value": "",
    "placeholder": "Enter industry",
    "user_id": 2,
    "display_order": 1,
    "created_at": "2025-05-22T16:45:23.123456Z",
    "updated_at": "2025-05-22T16:45:23.123456Z"
  },
  {
    "id": 2,
    "name": "Annual Revenue",
    "type": "number",
    "entity": "client",
    "required": false,
    "default_value": "",
    "placeholder": "Enter annual revenue",
    "user_id": 2,
    "display_order": 2,
    "created_at": "2025-05-22T16:45:23.123456Z",
    "updated_at": "2025-05-22T16:45:23.123456Z"
  },
  {
    "id": 3,
    "name": "Client Priority",
    "type": "dropdown",
    "entity": "client",
    "required": true,
    "options": ["Low", "Medium", "High", "Critical"],
    "default_value": "Medium",
    "user_id": 2,
    "display_order": 3,
    "created_at": "2025-05-22T16:45:23.123456Z",
    "updated_at": "2025-05-22T16:45:23.123456Z"
  }
]

Update Custom Field

Endpoint: PUT /api/custom-fields/{id}

Parameters:

  • id (path parameter): Custom field ID

Request Body: Same as create custom field with fields to update.

Response: The updated custom field.

Delete Custom Field

Endpoint: DELETE /api/custom-fields/{id}

Parameters:

  • id (path parameter): Custom field ID

Response: Success message.

Save Custom Field Value

Endpoint: POST /api/custom-field-values/{entity}/{entity_id}

Parameters:

  • entity (path parameter): Entity type (client, invoice, expense, project)
  • entity_id (path parameter): ID of the entity (client, invoice, etc.)

Request Body:

{
  "custom_field_id": 1,
  "value": "Technology"
}

Or multiple values at once:

[
  {
    "custom_field_id": 1,
    "value": "Technology"
  },
  {
    "custom_field_id": 2,
    "value": "1000000"
  },
  {
    "custom_field_id": 3,
    "value": "High"
  }
]

Response: The saved custom field value(s).

Error Handling

All API endpoints return appropriate HTTP status codes and error messages:

  • 200/201: Success
  • 400: Bad Request (validation errors, missing fields)
  • 401: Unauthorized (authentication failed)
  • 403: Forbidden (insufficient permissions)
  • 404: Not Found (resource not found)
  • 500: Internal Server Error

Error responses follow this format:

{
  "error": "Detailed error message"
}

Implementation Notes

  1. When adding a new contact person as primary, any existing primary contact for that client will automatically be demoted to non-primary.
  2. Custom fields for clients can be saved both during client creation and by using the dedicated custom field value endpoints.
  3. When displaying client information, be sure to handle both individual and organization categories appropriately, showing/hiding fields like company_registration_number based on the category.
  4. The client's contacts array will include all contact persons associated with the client, with the primary contact typically listed first.
  5. Banking details should be treated as sensitive information and displayed only when needed.