Global Request & Response Schemas

This page defines the common structures used across all Arkipel API messages.


Overview

Every API interaction follows a consistent message envelope pattern. Understanding these structures helps you:

  • Parse responses correctly
  • Handle authentication requirements
  • Implement pagination
  • Track asynchronous operations

Request Envelope

All requests to the API must include these top-level fields:

{
  "payload": {
    "type": "message:type",
    "...": "message-specific fields"
  },
  "timestamp": "2026-01-21T10:30:00Z",
  "signature": "hex_encoded_ed25519_signature",
  "source_public_key": "zbase32_encoded_public_key"
}

Request Fields

Field Type Required Description
payload Object Yes Contains the message type and data
payload.type String Yes Message type (e.g., people:query, organizations:upsert)
timestamp String Token auth ISO 8601 UTC timestamp (YYYY-MM-DDTHH:MM:SSZ)
signature String Keypair auth Ed25519 signature of the payload (hex encoded)
source_public_key String Keypair auth Your public key in ZBase32 format (52 characters)

Authentication Methods

API Token Authentication:

{
  "payload": { "type": "ping" },
  "timestamp": "2026-01-21T10:30:00Z"
}

Include Authorization: Bearer YOUR_TOKEN header.

Keypair Authentication:

{
  "payload": { "type": "ping" },
  "signature": "a1b2c3d4e5f6...",
  "source_public_key": "bwyexzko74pnnjn741936fnaujxyhib9rpx8rggtejwnc3cz6ans"
}

Response Envelope

All API responses follow this consistent structure:

{
  "source_public_key": "community_public_key",
  "source_site": {
    "protocol": "https",
    "fqdn": "arkipel.example.com"
  },
  "created_at": "2025-11-13T20:52:49Z",
  "signature": "hex_encoded_ed25519_signature",
  "payload": {
    "type": "message:type",
    "...": "response data"
  }
}

Response Fields

Field Type Description
source_public_key String The community’s public key
source_site.protocol String "http" or "https"
source_site.fqdn String Fully qualified domain name
created_at String ISO 8601 timestamp when message was processed
signature String Community’s Ed25519 signature (hex encoded)
payload Object Response data specific to the message type
payload.type String Same message type from your request

Verification

When using keypair authentication, you can verify the response signature:

  1. Extract payload from response
  2. Verify signature using the community’s public key
  3. This ensures the response is authentic and unmodified

Synchronous Response (Queries)

Query operations return data immediately:

{
  "source_public_key": "community_key",
  "source_site": { "protocol": "https", "fqdn": "..." },
  "created_at": "2025-11-13T20:52:49Z",
  "signature": "...",
  "payload": {
    "type": "people:query",
    "q": {
      "per_page": 20,
      "page": 1,
      "total": 150
    },
    "resources": [
      { "id": 1, "first_name": "John", "last_name": "Doe" }
    ]
  }
}

Asynchronous Response (Mutations)

Mutation operations return a message_id for status tracking:

{
  "source_public_key": "community_key",
  "source_site": { "protocol": "https", "fqdn": "..." },
  "created_at": "2025-11-13T20:52:49Z",
  "signature": "...",
  "payload": {
    "type": "people:upsert",
    "message_id": "6916452112f746b2b4cf48c1"
  }
}

Async Tracking

Use the message_id to check operation status:

Request:

{
  "payload": {
    "type": "arkipel_messages:query",
    "message_id": "6916452112f746b2b4cf48c1"
  }
}

Response:

{
  "payload": {
    "type": "arkipel_messages:query",
    "message_id": "6916452112f746b2b4cf48c1",
    "status": "persisted",
    "resource": { "id": 123, "first_name": "Jane", ... }
  }
}

Async Status Values

Status Meaning
pending Message received, waiting to be processed
processing Currently being processed
persisted Successfully completed, resource available
failed Processing failed, check error field
rejected Rejected by validation or policy

Pagination Schema

List queries support pagination through the q parameter:

Request

{
  "payload": {
    "type": "people:query",
    "q": {
      "page": 1,
      "per_page": 20
    }
  }
}

Pagination Parameters

Parameter Type Default Maximum Description
page Integer 1 - Page number (starts at 1)
per_page Integer 20 100 Records per page

Response

{
  "payload": {
    "type": "people:query",
    "q": {
      "per_page": 20,
      "page": 1,
      "total": 150
    },
    "resources": [ ... ]
  }
}

Pagination Response Fields

Field Type Description
payload.q.per_page Integer Records per page (as requested)
payload.q.page Integer Current page number
payload.q.total Integer Total number of records available

Calculating Pages

const totalPages = Math.ceil(total / per_page);
const hasNextPage = page < totalPages;
const hasPreviousPage = page > 1;

Error Response Schema

Error responses maintain the same envelope structure:

{
  "source_public_key": "community_key",
  "source_site": { "protocol": "https", "fqdn": "..." },
  "created_at": "2025-11-13T20:52:49Z",
  "signature": "...",
  "payload": {
    "type": "arkipel_messages:query",
    "message_id": "abc123",
    "status": "failed",
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "Invalid attribute: email format is invalid",
      "details": {
        "attribute": "email",
        "value": "invalid-email"
      }
    }
  }
}

Error Response Fields

Field Type Description
payload.status String "failed" or "rejected"
payload.error.code String Machine-readable error code
payload.error.message String Human-readable description
payload.error.details Object Additional context (field names, values, etc.)

See Error Codes for complete list of error codes and handling strategies.


Common Patterns

Nested Resources

Many messages support nested creation. The envelope structure remains the same, but payload contains nested objects:

{
  "payload": {
    "type": "households:upsert",
    "household": {
      "name": "Smith Family",
      "people": [
        { "first_name": "John", "last_name": "Smith" }
      ],
      "addresses": [
        { "country_code": "CA", "street1": "123 Main St" }
      ]
    }
  }
}

Partial Updates

Upsert operations support partial updates. Include only fields you want to change:

{
  "payload": {
    "type": "people:upsert",
    "id": 123,
    "note": "Updated note only"
  }
}

Omitted fields retain their existing values.



Return to API Specifications


Back to top

Welcome to the Arkipel DevKit! This documentation will guide you through everything you need to build clients for Arkipel communities.

Contact: devkit@arkipel.co | Page URLs

Copyright © 2026 Arkipel. Distributed under an MIT license.