Skip to content

/admin/domains

Path: /admin/domains
Namespace: admin
Resource: domains

Overview

The Domain resource represents tenants in the multi-tenant system. Each domain provides data isolation and can have its own configuration, users, invoices, items, and other resources.

Relationships

Model Associations

Domain connects to the following resources:

Address
  • Type: has_one via address_id
  • Field: address_id
  • Description: Domain's business address (used as default seller). Each domain can have one default business address.
  • Reverse: Address belongs to Domain (address.domain)
  • API Access:
    • Direct: Included in domain response as address_id and address object
    • Filter: GET /admin/domains.json?q[address_id_eq]=123
    • Via Address: GET /admin/addresses/:address_id.json (domain's business address)
  • Key Pattern: domain.address is automatically used as default seller when creating invoices if seller_id is omitted.
  • Related Documentation: Addresses
  • Example: Get domain's business address (included in domain response):
    javascript
    const domain = await fetch('/admin/domains/1.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
    const address = domain.domain.address; // Address is included in domain response
Domain (Self-Referential - Hierarchical)
  • Type: belongs_to / has_many via host_id
  • Field: host_id
  • Description: Parent domain for hierarchical multi-tenancy. Domains can have parent/child relationships for organizational structures.
  • Reverse: Domain has many sub-domains (domain.domains or domain.children)
  • API Access:
    • Direct: Included in domain response as host_id (parent domain ID)
    • Filter: GET /admin/domains.json?q[host_id_eq]=1
    • Nested: GET /admin/domains/:id/domains.json (sub-domains for a specific domain)
  • Example: Get all sub-domains:
    javascript
    const subDomains = await fetch('/admin/domains/1/domains.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Domain[] (Multi-Domain Item Visibility)
  • Type: has_and_belongs_to_many via domains_items join table
  • Description: Items accessible to this domain. Items can be visible to multiple domains (multi-domain visibility).
  • Reverse: Item has many domains via domains_items join table
  • API Access:
    • Direct: Included in domain response as items array (if present)
    • Filter: GET /admin/items.json?q[domains_id_eq]=1 (items visible to domain)
  • Related Documentation: Items
  • Example: Get all items accessible to a domain:
    javascript
    const items = await fetch('/admin/items.json?q[domains_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Reverse Associations

The following resources connect to Domain (all scoped by host_id):

User[]
  • Type: has_many on User via host_id
  • Description: All users for this domain. Users belong to domains and can only access their domain's data.
  • API Access:
    • Filter: GET /admin/users.json?q[host_id_eq]=1
  • Related Documentation: Users
  • Example: Get all users for a domain:
    javascript
    const users = await fetch('/admin/users.json?q[host_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Invoice[]
  • Type: has_many on Invoice via host_id
  • Description: All invoices for this domain. Invoices are scoped to domains for multi-tenant isolation.
  • API Access:
    • Filter: GET /admin/invoices.json?q[host_id_eq]=1
  • Related Documentation: Invoices
  • Example: Get all invoices for a domain:
    javascript
    const invoices = await fetch('/admin/invoices.json?q[host_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Address[]
  • Type: has_many on Address via host_id
  • Description: All addresses for this domain. Addresses are scoped to domains for multi-tenant isolation.
  • API Access:
    • Filter: GET /admin/addresses.json?q[host_id_eq]=1
  • Related Documentation: Addresses
  • Example: Get all addresses for a domain:
    javascript
    const addresses = await fetch('/admin/addresses.json?q[host_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Payment[]
  • Type: has_many on Payment via host_id
  • Description: All payments for this domain. Payments are scoped to domains.
  • API Access:
    • Filter: GET /admin/payments.json?q[host_id_eq]=1
  • Related Documentation: Payments
Item[]
  • Type: has_many on Item via host_id (plus has_and_belongs_to_many via domains_items)
  • Description: Items owned by this domain and items visible to this domain (via multi-domain visibility).
  • API Access:
    • Filter: GET /admin/items.json?q[host_id_eq]=1 (items owned by domain)
    • Filter: GET /admin/items.json?q[domains_id_eq]=1 (items visible to domain)
  • Related Documentation: Items
AccountingAccount[]
  • Type: has_many on AccountingAccount via host_id
  • Description: Accounting accounts for this domain. Chart of accounts is scoped to domains.
  • API Access:
    • Filter: GET /admin/accounting_accounts.json?q[host_id_eq]=1
  • Related Documentation: Accounting
AccountingEquation[]
  • Type: has_many on AccountingEquation via host_id
  • Description: Accounting transactions for this domain. Accounting equations are scoped to domains.
  • API Access:
    • Filter: GET /admin/accounting_equations.json?q[host_id_eq]=1
  • Related Documentation: Accounting
SalesAgreement[]
  • Type: has_many on SalesAgreement via host_id
  • Description: Sales agreements for this domain. Sales agreements are scoped to domains.
  • API Access:
    • Filter: GET /admin/sales_agreements.json?q[host_id_eq]=1
  • Related Documentation: Sales Agreements

Relationship Patterns

Domain Address as Default Seller
  • Use Case: Use domain's business address as default seller when creating invoices
  • Example: When seller_id is omitted, domain.address is automatically used:
    javascript
    const invoice = await fetch('/admin/invoices.json', {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify({
        invoice: {
          invoice_type: 'invoice',
          buyer_id: 2,
          // seller_id omitted - domain.address used automatically
          date: '2024-01-15'
        }
      })
    }).then(r => r.json());
Hierarchical Domain Structure
  • Use Case: Navigate parent-child relationships for organizational domain structures
  • Example: Get all sub-domains:
    javascript
    const subDomains = await fetch('/admin/domains.json?q[host_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Multi-Domain Item Visibility
  • Use Case: Make items visible to multiple domains
  • Example: Filter items visible to a specific domain:
    javascript
    const visibleItems = await fetch('/admin/items.json?q[domains_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Domain Resource Filtering
  • Use Case: Get all resources for a specific domain
  • Example: Get all invoices for a domain:
    javascript
    const domainInvoices = await fetch('/admin/invoices.json?q[host_id_eq]=1', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Key Features

  • Multi-Tenancy: Each domain is isolated from others
  • Host Association: Domains belong to a host
  • Status Management: active, inactive status
  • SSL Configuration: SSL certificate management (enable_ssl, disable_ssl)
  • Domain Hierarchy: Domains can have parent/child relationships
  • Data Isolation: All resources are scoped to domains

Multi-Tenant Architecture

  • Host-Based Isolation: Data is scoped to domains via host associations
  • Resource Scoping: All resources (invoices, addresses, items, etc.) are scoped to domains
  • User Access: Users belong to domains and can only access their domain's data
  • Domain Configuration: Each domain can have its own locale, timezone, and metadata

Available Operations

List Domains (GET)

Endpoint: GET /admin/domains.json

Query Parameters:

  • q[field_predicate]=value - Ransack query filters for advanced filtering
  • scope=name - Apply named scope (e.g., active, inactive)
  • page=N - Page number for pagination
  • per_page=N - Items per page (default: 25)

Request Examples:

bash
curl -X GET "https://your-company.erpax.com/admin/domains.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/admin/domains.json?q[name_cont]=Company" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/domains.json?scope=active" \
  -H "Accept: application/json"

JavaScript Example:

javascript
const response = await fetch('/admin/domains.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "domains": [
    {
      "id": 1,
      "name": "company.erpax.com",
      "host_id": null,
      "status": "active",
      "ssl_enabled": true,
      "address_id": 1,
      "created_at": "2024-01-10T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 1,
    "total_count": 5
  }
}

Show Domain (GET /:id)

Endpoint: GET /admin/domains/:id.json

Request Example:

bash
curl -X GET "https://your-company.erpax.com/admin/domains/1.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

JavaScript Example:

javascript
const response = await fetch('/admin/domains/1.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const domain = await response.json();

Response (200 OK):

json
{
  "domain": {
    "id": 1,
    "name": "company.erpax.com",
    "host_id": null,
    "status": "active",
    "ssl_enabled": true,
    "address_id": 1,
    "locale": "en",
    "timezone": "UTC",
    "created_at": "2024-01-10T10:00:00Z",
    "updated_at": "2024-01-15T12:00:00Z"
  }
}

Create Domain (POST)

Endpoint: POST /admin/domains.json

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/domains.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "domain": {
      "name": "newcompany.erpax.com",
      "status": "active",
      "address_id": 2,
      "locale": "en",
      "timezone": "America/New_York"
    }
  }'

JavaScript Example:

javascript
const response = await fetch('/admin/domains.json', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    domain: {
      name: 'newcompany.erpax.com',
      status: 'active',
      address_id: 2,
      locale: 'en',
      timezone: 'America/New_York'
    }
  })
});
const domain = await response.json();

Response (201 Created):

json
{
  "domain": {
    "id": 2,
    "name": "newcompany.erpax.com",
    "status": "active",
    "created_at": "2024-01-15T14:30:00Z"
  }
}

Update Domain (PATCH /:id)

Endpoint: PATCH /admin/domains/:id.json

Request Example:

bash
curl -X PATCH "https://your-company.erpax.com/admin/domains/1.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "domain": {
      "status": "inactive"
    }
  }'

Response (200 OK):

json
{
  "domain": {
    "id": 1,
    "status": "inactive",
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Delete Domain (DELETE /:id)

Endpoint: DELETE /admin/domains/:id.json

Request Example:

bash
curl -X DELETE "https://your-company.erpax.com/admin/domains/1.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (204 No Content):

(empty response)

Batch Actions

Endpoint: POST /admin/domains/batch_action.json

Available batch actions:

  • activate - Activate selected domains
  • suspend - Suspend selected domains
  • enable_ssl - Enable SSL for selected domains
  • disable_ssl - Disable SSL for selected domains
  • create_archive - Create archive for selected domains

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/domains/batch_action.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "batch_action": "activate",
    "collection_selection": [1, 2, 3]
  }'

Member Actions

Custom actions available on individual domains via API:

Activate Domain

Endpoint: POST /admin/domains/:id/activate

Description: Activate the domain.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/domains/1/activate" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "domain": {
    "id": 1,
    "status": "active",
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Suspend Domain

Endpoint: POST /admin/domains/:id/suspend

Description: Suspend the domain.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/domains/1/suspend" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "domain": {
    "id": 1,
    "status": "inactive",
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Enable SSL

Endpoint: POST /admin/domains/:id/enable_ssl

Description: Enable SSL/TLS for the domain.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/domains/1/enable_ssl" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "domain": {
    "id": 1,
    "ssl_enabled": true,
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Disable SSL

Endpoint: POST /admin/domains/:id/disable_ssl

Description: Disable SSL/TLS for the domain.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/domains/1/disable_ssl" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "domain": {
    "id": 1,
    "ssl_enabled": false,
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Scopes

  • all (default) - All domains
  • active - Active domains
  • inactive - Inactive domains

Usage Example:

bash
GET /admin/domains.json?scope=active
GET /admin/domains.json?scope=inactive

Filters

Available filters for searching and filtering domains:

  • name_cont - Text filter - Search by domain name (contains)
  • host - Select filter - Filter by host domain
  • status - Select filter - Filter by status (active, inactive)
  • ssl_enabled - Boolean filter - Filter by SSL enabled status
  • created_at - Date filter - Filter by creation date
  • updated_at - Date filter - Filter by update date

Filtering Examples:

bash
# Search by name
GET /admin/domains.json?q[name_cont]=company

# Filter by status
GET /admin/domains.json?q[status_eq]=active

# Filter by SSL
GET /admin/domains.json?q[ssl_enabled_eq]=true

Business Rules

  • Name Uniqueness: Domain names must be unique
  • Host Association: Domains must belong to a host (or be root domains)
  • Data Isolation: All resources are automatically scoped to domains
  • Address Association: Domains can have an associated address used as default seller
  • Status Management: Only active domains can be accessed by users
  • Users - Users belong to domains
  • Invoices - Invoices are scoped to domains
  • Addresses - Addresses are scoped to domains
  • Items - Items are scoped to domains

Released under an open source license.