Arkipel API Connection

All requests to the /arkipel/{community_public_key}/streams endpoint must adhere to the following requirements:

1. Endpoint Structure

  • URL Format: https://{site_url}/arkipel/{community_public_key}/streams Replace {site_url} with the base URL of the Arkipel server and {community_public_key} with the server’s public key.

2. HTTP Configuration

  • Method: POST
  • Headers:
    • Content-Type: application/json
    • Accept: application/json
  • Standard Timeout Defaults:
    • Open Timeout: 5 seconds (connection establishment)
    • Read Timeout: 10 seconds (response waiting)
  • SSL/TLS:
    • SSL verification is disabled in the example (VERIFY_NONE). In production, always enable SSL verification (VERIFY_PEER) for security.

3. Request Body

  • The request body must be a valid JSON object matching the schema of the message type you are sending (e.g., people:upsert, arkipel_messages:query).

Example Setup (Ruby)

request_body = { ... }
uri = URI.parse("#{site_url}/arkipel/#{community_public_key}/streams")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = site_url.start_with?("https")
http.open_timeout = 5      # Connection timeout
http.read_timeout = 10     # Response timeout
http.verify_mode = OpenSSL::SSL::VERIFY_PEER  # Enable in production!
request = Net::HTTP::Post.new(uri.request_uri,
  "Content-Type" => "application/json",
  "Accept" => "application/json"
)
request.body = request_body.to_json

4. Authentication

We offer 2 ways to authenticate requests:

  • Keypairs (The preferred method)
  • API Tokens

Main differences

Feature Keypair Authentication API Tokens
Integration ✅ 1 keypair for all communities. ❌ 1 token per community to manage.
Security ✅ Uses public/private key cryptography. Only the key holder can sign requests. ❌ Acts like a password. If leaked, anyone can use it.
Auditability ✅ Every request is signed. You can verify who sent it. ❌ No way to prove who used the token.
Future Features ✅ Unlocks advanced features (e.g., fine-grained permissions, automation). ❌ Limited to basic access.
Industry Standard ✅ Used in SSH, TLS, and blockchain. More trusted. ❌ Simpler but less secure.
Setup ⚠️ Requires initial setup (generate keys, sign requests). ✅ Easier to start with.
Scalability ✅ Scales securely for teams and automation. ❌ Riskier at scale.
Best For 🔒 Production, sensitive data, or advanced use cases. 🛠️ Quick testing or low-risk scenarios.

Right now, both keypair authentication and API tokens work for basic access. But in the future, we’ll add advanced features that will only be available with keypair authentication. Since keypairs are more secure, they’ll unlock these powerful tools while keeping your account safe.”

4.1 Keypair Authentication Example (Bash)

To authenticate your request, you need to sign the payload with your private key (the one paired with your integrator_public_key). This signature proves that the request is genuinely coming from you and hasn’t been tampered with.

Here’s how to send a signed request using curl:

curl -X POST \
  "#{site_url}/arkipel/#{community_public_key}/streams" \
  -H "Content-Type: application/json" \
  -d '{
    "source_public_key": "YOUR_PUBLIC_KEY_HERE",
    "timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
    "signature": "YOUR_SIGNED_PAYLOAD_HERE",
    "payload": {
      "type": "ping"
    }
  }'

4.2 API Token Authentication Example (Bash)

To authenticate your request using an API token, include it in the Authorization header as a Bearer token. This token acts like a password, granting your request access to the Arkipel community.

Here’s how to send a request using curl:

curl -X POST \
  "#{site_url}/arkipel/#{community_public_key}/streams" \
  -H "Authorization: Bearer YOUR_API_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
    "payload": {
      "type": "ping"
    }
  }'

5. Rate Limiting

The Arkipel API implements rate limiting to ensure fair usage and maintain service stability for all communities.

Rate Limit Details

  • Limit: 100 requests per minute per identifier
  • Identifier: Either your source_public_key (for keypair authentication) or your API token
  • Window: Rolling 60-second window
  • Status: HTTP 429 (Too Many Requests) when exceeded

What Happens When You Hit the Limit

When you exceed the rate limit, the API returns a 429 Too Many Requests response with details about when you can retry:

curl -X POST \
  "#{site_url}/arkipel/#{community_public_key}/streams" \
  -H "Authorization: Bearer YOUR_API_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{"payload": {"type": "ping"}}'

Response (HTTP 429):

{
  "error": "Rate limit exceeded: 100 requests per minute",
  "retry_after": 45
}

Handling Rate Limit Errors

When you receive a 429 response, your client should:

  1. Pause requests - Stop sending new requests immediately
  2. Wait for the retry window - Use the retry_after value (in seconds) to know when to resume
  3. Implement exponential backoff - If you continue to hit limits, increase wait times between retries
  4. Queue requests - Buffer requests and send them at a sustainable rate

Ruby Example: Rate Limit Handler

def send_with_rate_limit_handling(payload, max_retries: 3)
  retries = 0

  begin
    response = http_client.post(payload)

    if response.code == '429'
      error_data = JSON.parse(response.body)
      retry_after = error_data['retry_after'] || 60

      if retries < max_retries
        retries += 1
        sleep(retry_after)
        retry
      else
        raise "Rate limit exceeded after #{max_retries} retries"
      end
    end

    response
  rescue JSON::ParserError
    raise "Invalid rate limit response"
  end
end

Best Practices

  • Monitor your usage - Track request counts to stay within limits
  • Implement client-side rate limiting - Add delays between requests to stay under 100/minute
  • Handle 429 gracefully - Never ignore rate limit errors; always implement retry logic

Exemptions

Certain public keys and IP addresses may be exempt from rate limiting (configured by community administrators). If you need higher limits for legitimate use cases, contact the community administrator to discuss whitelist options.

6. Security Note

  • SSL Verification: The example disables SSL verification (VERIFY_NONE) for simplicity. In production, always set verify_mode = OpenSSL::SSL::VERIFY_PEER to ensure secure communication.
  • Authentication: Ensure the community_public_key is valid and authorized for the target community.

7. Why These Constraints?

  • Timeouts: Prevent hanging connections and improve reliability.
  • SSL: Protects data integrity and confidentiality (enable verification in production).
  • JSON: Ensures consistent data formatting for all message types.