4klyft API (1.0.0)

Download OpenAPI specification:

4klyft API Support: [email protected] License: Proprietary

Commerce and order-fulfilment platform API for 4klyft.

Overview

This API provides endpoints for managing:

  • Catalog (PIM/DAM): products, variants, attributes, options, categories, brands, collections, assortments, and media
  • Sales: orders, customers, merchants, sales channels, and channel order import
  • Inventory: stock items, levels, lots, and serial units across custodians
  • Warehousing & Operations: goods receipt/issue, holds, and custodian operations
  • Fulfilment: fulfilment orders dispatched to third-party (3PL) providers
  • Shipping: carriers, shipments, labels, tracking, returns, and proof of delivery
  • Finance & Billing: payments, settlements, invoices, credit notes, tax, and subscriptions
  • Integration: sales-channel connections, providers, webhooks, and catalog/order sync
  • Documents: operational document generation and requests
  • Storage: file/drive storage with chunked upload and signed access
  • Identity & Access (IAM): authentication, users, roles, permissions, and tenants
  • Platform services: notifications, scheduling, numbering, data exchange, analytics, and workspace tables & views

Authentication

All API endpoints (except /api/docs and /api/v1/iam/auth/*) require JWT Bearer token authentication. Include the token in the Authorization header:

Authorization: Bearer <your-jwt-token>

Rate Limiting

Every /api/ request is rate-limited per caller — by your authenticated identity when a token is present, otherwise by client IP. The authentication endpoints (/auth/login, /auth/refresh, /auth/request-password-reset) carry stricter, IP-based limits.

Each response advertises your current budget via headers:

  • X-RateLimit-Limit — the bucket size
  • X-RateLimit-Remaining — tokens left in the current window
  • X-RateLimit-Reset — Unix timestamp when a token next frees up

Exceeding a limit returns 429 Too Many Requests (RFC 6585) with a Retry-After header (seconds to wait). Back off and retry after the indicated delay rather than hammering the endpoint.

Error Handling

The API uses RFC 7807 Problem Details for error responses.

Authorization

Per-entity ability probe endpoint.

The UI calls POST /api/auth/can to ask "given the user's current scopes

  • AND the entity's current state, would these actions be allowed?" — BEFORE firing the actual command.

The response is a flat map keyed by the requested scope. Each entry has:

  • allowed (bool) — combined verdict (scope held AND state allows)
  • reason (string) — present on denials, suitable for tooltip display

Backend always remains authoritative via the bus AuthorizationStage; this endpoint is advisory and intended purely to drive UI gating.

Probe per-entity abilities

Returns a map of scope → verdict for the current user against an optional subject entity. Both the user-holds-scope check and the entity-state check must pass for allowed to be true.

Authorizations:
Bearer
Request Body schema: application/json
required

Subject URI (optional) and a list of scopes to probe

subject
string

ResourceUri of the entity being probed. Omit for scope-only checks.

scopes
required
Array of strings [ 1 .. 50 ] items

Responses

Request samples

Content type
application/json
{
  • "subject": "glacia:///document/documents/01KT0000000000000000000000",
  • "scopes": [
    ]
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Authentication

Authentication API Resource.

Delete account (GDPR right to erasure)

Permanently anonymizes the authenticated user account. All PII is removed. This action is irreversible.

Authorizations:
Bearer

Responses

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Mint a single-use code that hands this session to another 4klyft property

Called by the app for a signed-in visitor on their way to a satellite (the help centre, for example). The satellite never collects a password: it redirects here, and the code is exchanged for tokens by its server. Grants nothing new — the caller already holds the session it hands over.

Authorizations:
Bearer
Request Body schema: application/json
required

Which satellite, where it may be redeemed, and the PKCE challenge

clientId
required
string

Registered satellite id, e.g. "help"

redirectUri
required
string

Must match one registered for the client exactly

codeChallenge
required
string

base64url(SHA-256(verifier)), 43 characters

Responses

Request samples

Content type
application/json
{
  • "clientId": "string",
  • "redirectUri": "string",
  • "codeChallenge": "string"
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Exchange a handoff code for tokens

Called by a satellite SERVER, never its browser. The client secret is what makes a code lifted from a URL worthless. Tokens are issued against the same session the code came from, so one logout ends every property at once.

Request Body schema: application/json
required

The code, the calling client, and the PKCE verifier

code
required
string
clientId
required
string
clientSecret
required
string
codeVerifier
required
string

Responses

Request samples

Content type
application/json
{
  • "code": "string",
  • "clientId": "string",
  • "clientSecret": "string",
  • "codeVerifier": "string"
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

User login

Authenticate a user with email and password. Returns access and refresh tokens.

Request Body schema: application/json
required

Login credentials

email
required
string <email>

User email address

password
required
string <password>

User password

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

User logout

Invalidate the current session.

Authorizations:
Bearer

Responses

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Logout from all devices

Revoke all active sessions for the authenticated identity.

Authorizations:
Bearer

Responses

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Logout from other devices

Revoke all active sessions for the authenticated identity except the current one.

Authorizations:
Bearer

Responses

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Refresh access token

Use a refresh token to obtain a new access token.

Request Body schema: application/json
required

Refresh token

refreshToken
required
string

The refresh token

Responses

Request samples

Content type
application/json
{
  • "refreshToken": "string"
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Self-serve registration

Create a new account with email and password. No tokens are returned — a verification email is sent and the user must verify, then log in.

Request Body schema: application/json
required

Registration details

email
required
string <email>

User email address

password
required
string <password>

Password (minimum 8 characters)

firstName
required
string

First name

company
string

Company / organization name (optional; used for the first-organization step after verification)

country
string

Country (optional)

marketingOptIn
boolean
Default: false

Consent to marketing communications

Responses

Request samples

Content type
application/json
{
  • "email": "[email protected]",
  • "password": "your-secure-password",
  • "firstName": "Alex",
  • "company": "string",
  • "country": "string",
  • "marketingOptIn": false
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Request password reset

Request a password reset email. Always returns success to avoid leaking email existence.

Request Body schema: application/json
required

Email address

email
required
string <email>

The email address associated with the account

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Resend email verification

Request a new verification email. Always returns success to avoid leaking email existence.

Request Body schema: application/json
required

Email address

email
required
string <email>

Email address to resend verification to

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Reset password

Submit the token received by email along with a new password to complete the password reset.

Request Body schema: application/json
required

Reset token and new password

token
required
string

The password reset token received by email

newPassword
required
string <password>

The new password (minimum 8 characters)

Responses

Request samples

Content type
application/json
{
  • "token": "string",
  • "newPassword": "pa$$word"
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Select tenant

Validates membership and issues a tenant-scoped access token. Include this token as Bearer in subsequent requests to operate within the selected tenant.

Authorizations:
Bearer
Request Body schema: application/json
required

Tenant selection

tenantId
required
string

ULID of the tenant to operate under

Responses

Request samples

Content type
application/json
{
  • "tenantId": "01HQWXYZ1234567890TENANT"
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

Verify email address

Submit the token received by email to verify the email address. No authentication required.

Request Body schema: application/json
required

Verification token

token
required
string

The verification token received by email

Responses

Request samples

Content type
application/json
{
  • "token": "string"
}

Response samples

Content type
{
  • "type": "/errors/validation-error",
  • "title": "Validation Error",
  • "status": 400,
  • "detail": "The provided input is invalid",
  • "violations": [
    ],
  • "instance": "string"
}

IAM / External identity

Social-signup / SSO entry-point endpoints.

POST /api/iam/auth/external/{kind}/start Mints a signed HMAC state token and returns the provider's authorization URL the browser must navigate to (or feed into a client-side SDK such as Apple's AppleID.auth.init). Same JSON contract as StorageOAuthResource on the Storage module.

The callback half of the flow lives on a separate invokable Symfony route (ExternalIdentityCallbackProvider) because the OAuth callback returns a redirect (with the freshly-issued tokens in the URL fragment) — that response shape does not fit API Platform's resource serialization.

Public route (no auth required) — see iam/prepend/security.yaml.

Begin an external-identity (social / SSO) authentication flow

Mints an HMAC-signed state token and returns the provider authorization URL the browser must navigate to. The same JSON shape is consumed by client-side SDK flows (e.g. Apple JS SDK).

Authorizations:
Bearer
path Parameters
kind
required
string
Enum: "google_oauth" "facebook_oauth" "apple_oauth" "oidc" "saml"

Provider discriminator

Request Body schema: application/json
optional

Optional return URI overriding the platform default.

returnUri
string or null

Final user-facing URL to bounce to after the callback succeeds. Must match the configured allow-list when one is set.

Responses

Request samples

Content type
application/json
{
  • "returnUri": "string"
}

Response samples

Content type
{
  • "@context": "string",
  • "@id": "string",
  • "@type": "string",
  • "id": "string",
  • "kind": "string",
  • "authorizationUrl": "string",
  • "state": "string",
  • "redirectUri": "string",
  • "returnUri": "string",
  • "expiresInSeconds": 0
}