Skip to content

Client architecture

The SDK has four layers.

1. Configuration

Configuration owns the deployment base URL, bearer credential, timeout, user-agent, and retry policy. It contains no organization identifier. Organization scope remains a property of the credential and of route parameters.

2. Request executor

RequestExecutor converts an API service call into a PSR-7 request, adds bearer authentication and JSON headers, sends the request through PSR-18, applies the retry policy, decodes JSON, and maps error statuses to exceptions.

The low-level transport rejects absolute request paths to prevent a caller-supplied path from redirecting the configured credential to another host.

3. API services

Service classes are thin route mappings:

  • OrganizationsApi
  • ProjectsApi
  • BoardsApi
  • TicketsApi
  • DocumentsApi
  • NotificationsApi

They construct route paths, query parameters, and request bodies. They do not contain persistence, caching, or background behavior.

4. Requests, responses, and models

Create request classes are immutable value objects. PATCH request classes are clone-based builders where an omitted property and an explicit JSON null remain different.

All API methods return ApiResponse. Models such as Project, Board, Ticket, and Document are optional hydration helpers for OpenAPI component schemas.

Dependency direction

Your application
    |
    v
OkatanaClient
    |
    +--> API service
    |       |
    |       +--> request DTO / query DTO
    |
    +--> RequestExecutor
            |
            +--> PSR-17 factories
            +--> PSR-18 client
            +--> RetryPolicy
            +--> PSR-3 logger
            |
            +--> ApiResponse / exceptions

Why PSR-18

The SDK does not force a specific HTTP stack. Guzzle is included as a default, but the core executor depends on PSR client and message abstractions. This maintains compatibility with applications standardizing on other implementations.