Skip to content

API Reference

The Productify Framework Manager provides both GraphQL and REST APIs for programmatic access to all platform features.

Base URLs

  • GraphQL Endpoint: POST /query
  • GraphQL Playground (dev only): GET /gql
  • REST API: /api/*

Authentication

The Manager supports three authentication methods:

1. Bearer Token (Personal Access Tokens)

Personal Access Tokens (PATs) provide secure API access for users.

Header Format:

http
Authorization: Bearer <your-token>

Creating a PAT:

graphql
mutation {
  createPersonalAccessToken(
    name: "My API Token"
    expiresAt: "2025-12-31T23:59:59Z"
  ) {
    token
    personalAccessToken {
      id
      name
      tokenPrefix
      expiresAt
      createdAt
    }
  }
}

WARNING

The token is only shown once during creation and cannot be retrieved later. Store it securely.

2. Machine User Authentication

Machine users enable backend services to authenticate with the Manager.

Bearer Token (Recommended):

http
Authorization: Bearer <machine-user-token>

Basic Authentication:

http
Authorization: Basic <base64(username:password)>

Creating a Machine User:

graphql
mutation {
  createMachineUserWithCredentials(
    tenantId: "tenant-uuid"
    input: {
      name: "Backend Service"
      username: "backend-service"
      hashedKey: "__GENERATE_TOKEN__"
      enabled: true
    }
  ) {
    generatedToken
    machineUser {
      id
      username
    }
  }
}

3. User Session (OAuth/OIDC)

Standard web session authentication via OAuth/OIDC providers configured in the Manager.


GraphQL API

Schema Overview

The GraphQL API provides type-safe access to all Manager resources with filtering, ordering, and pagination support.

GraphQL Playground: Access at /gql in development mode to explore the schema interactively.

Common Types

Filter

graphql
input Filter {
  field: String!
  value: String!
}

Order

graphql
input Order {
  field: String!
  direction: OrderDirection!
}

enum OrderDirection {
  ASC
  DESC
}

Pagination

graphql
input Pagination {
  limit: Int!
  offset: Int!
}

Endpoint Types

Authentication Types:

graphql
enum EndpointAuthType {
  Basic # HTTP Basic Authentication
  Bearer # Bearer Token Authentication
  None # No authentication required
}

Message Types:

graphql
enum EndpointInputMessageType {
  SOAP # SOAP XML message
  XML # Plain XML
  JSON # JSON payload
}

enum EndpointOutputMessageType {
  SOAP # SOAP XML message
  XML # Plain XML
  JSON # JSON payload
}

Log Levels:

graphql
enum EndpointLogLevel {
  NONE # No logging
  BASIC # Log metadata only (headers, status, timing)
  FULL # Log full request/response bodies
}

Queries

Projects

List Projects

graphql
query {
  projects(
    filters: []
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 10, offset: 0 }
  ) {
    id
    name
    slug
    description
    createdAt
  }
}

Get Project by Slug

graphql
query {
  project(slug: "my-project") {
    id
    name
    slug
    description
    tenants {
      id
      name
    }
  }
}

Tenants

List Tenants

graphql
query {
  tenants(
    projectSlug: "my-project"
    filters: []
    order: { field: "name", direction: ASC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    name
    slug
    description
  }
}

Get Tenant

graphql
query {
  tenant(projectId: "project-uuid", slug: "tenant-slug") {
    id
    name
    slug
    applications {
      id
      name
    }
  }
}

Applications

List Applications

graphql
query {
  applications(
    tenantSlug: "tenant-slug"
    filters: []
    order: { field: "name", direction: ASC }
    pagination: { limit: 10, offset: 0 }
  ) {
    id
    name
    slug
    description
    endpoints {
      id
      name
      url
    }
  }
}

Get Application

graphql
query {
  application(
    projectId: "project-uuid"
    tenantId: "tenant-uuid"
    slug: "app-slug"
  ) {
    id
    name
    slug
    description
    triggers {
      id
      name
      cronExpression
      enabled
    }
  }
}

Settings

Get Settings (Inherited)

graphql
query {
  settings(
    project: "project-uuid"
    tenant: "tenant-uuid"
    application: "app-uuid"
  ) {
    id
    backendSetting {
      id
      moduleConfig {
        EnabledModules
        KeyValuePairs {
          Key
          Value
        }
      }
    }
    frontendSetting {
      id
      moduleConfig {
        EnabledThemes
        DefaultTheme
        EnabledLocales
        DefaultLocale
      }
    }
  }
}

Configuration Inheritance

Settings follow a three-layer hierarchy: Project → Tenant → Application. Query at any level to get the effective merged configuration.

Endpoints

List Endpoints

graphql
query {
  endpoints(
    application: "app-uuid"
    filters: []
    order: { field: "name", direction: ASC }
    pagination: { limit: 50, offset: 0 }
  ) {
    id
    name
    description
    enabled
    url
    consumeURL
    authType
  }
}

Triggers

List Triggers

graphql
query {
  triggers(
    application: "app-uuid"
    filters: []
    order: { field: "name", direction: ASC }
    pagination: { limit: 50, offset: 0 }
  ) {
    id
    name
    cronExpression
    enabled
    createdAt
    updatedAt
  }
}

Machine Users

List Machine Users

graphql
query {
  machineUsers(
    tenant: "tenant-uuid"
    filters: []
    order: { field: "name", direction: ASC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    name
    username
    enabled
    tokenPrefix
  }
}

Language Packs

List Language Packs

graphql
query {
  languagePacks(
    project: "project-uuid"
    filters: []
    order: { field: "name", direction: ASC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    name
    content {
      Key
      Value
    }
  }
}

Personal Access Tokens

List My Personal Access Tokens

graphql
query {
  myPersonalAccessTokens(
    filters: []
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    name
    tokenPrefix
    expiresAt
    createdAt
    lastUsedAt
  }
}

List Personal Access Tokens (Cursor-based)

graphql
query {
  personalAccessTokens(first: 20, after: "cursor-string") {
    edges {
      node {
        id
        name
        tokenPrefix
        expiresAt
        createdAt
        lastUsedAt
      }
      cursor
    }
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    totalCount
  }
}

Token Security

Only the token prefix is visible after creation. The full token is only shown once during creation.

Users

Get Current User

graphql
query {
  me {
    id
    username
    email
    displayName
    disabled
  }
}

List Users

graphql
query {
  users(
    filters: []
    order: { field: "username", direction: ASC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    username
    email
    displayName
  }
}

Search Provider Users

graphql
query {
  userProviderSearch(name: "john") {
    id
    username
    email
    displayName
    disabled
  }
}

User Relationships

List User-Application Relations

graphql
query {
  user2applications(
    application: "app-uuid"
    filters: []
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    role
    user {
      id
      username
      email
    }
    application {
      id
      name
    }
  }
}

Get User-Application Relation

graphql
query {
  user2application(application: "app-uuid", id: "relation-uuid") {
    id
    role
    user {
      username
    }
  }
}

List User-Project Relations

graphql
query {
  user2projects(
    project: "project-uuid"
    filters: []
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    role
    user {
      id
      username
      email
    }
    project {
      id
      name
    }
  }
}

Get User-Project Relation

graphql
query {
  user2project(project: "project-uuid", id: "relation-uuid") {
    id
    role
    user {
      username
    }
  }
}

List User-Tenant Relations

graphql
query {
  user2tenants(
    tenant: "tenant-uuid"
    filters: []
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    role
    user {
      id
      username
      email
    }
    tenant {
      id
      name
    }
  }
}

Get User-Tenant Relation

graphql
query {
  user2tenant(tenant: "tenant-uuid", id: "relation-uuid") {
    id
    role
    user {
      username
    }
  }
}

Machine User to Endpoint Relations

List Machine User-Endpoint Relations

graphql
query {
  machineUser2endpoints(
    endpoint: "endpoint-uuid"
    filters: []
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    enabled
    machineUser {
      id
      username
    }
    endpoint {
      id
      name
    }
  }
}

Get Machine User-Endpoint Relation

graphql
query {
  machineUser2endpoint(endpoint: "endpoint-uuid", id: "relation-uuid") {
    id
    enabled
  }
}

Audit Logs

List Audit Logs

graphql
query {
  auditLogs(
    projectID: "project-uuid"
    filters: [{ field: "action", value: "create" }]
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 50, offset: 0 }
  ) {
    id
    entityType
    entityID
    action
    description
    metadata
    changes
    ipAddress
    userAgent
    createdAt
    user {
      username
    }
  }
}

Pilet Packages

List Pilet Packages

graphql
query {
  piletPackages(projectId: "project-uuid", enabled: true) {
    packages {
      id
      name
      version
      description
      size
      hash
      enabled
      createdAt
      updatedAt
    }
    count
  }
}

Get Pilet Package

graphql
query {
  piletPackage(
    projectId: "project-uuid"
    name: "@my-org/my-pilet"
    version: "1.0.0"
  ) {
    id
    name
    version
    description
    size
    hash
    enabled
    createdAt
    updatedAt
  }
}

Mutations

Project Management

Create Project

graphql
mutation {
  createProject(input: { name: "My Project", slug: "my-project" }) {
    id
    name
    slug
  }
}

Update Project

graphql
mutation {
  updateProject(
    id: "project-uuid"
    input: { name: "Updated Project Name", description: "New description" }
  ) {
    id
    name
    description
  }
}

Delete Project

graphql
mutation {
  deleteProject(id: "project-uuid")
}

Tenant Management

Create Tenant

graphql
mutation {
  createTenant(
    projectId: "project-uuid"
    input: { name: "Customer A", slug: "customer-a", type: run }
  ) {
    id
    name
    slug
    type
  }
}

Update Tenant

graphql
mutation {
  updateTenant(id: "tenant-uuid", input: { name: "Updated Customer Name" }) {
    id
    name
  }
}

Delete Tenant

graphql
mutation {
  deleteTenant(id: "tenant-uuid")
}

Application Management

Create Application

graphql
mutation {
  createApplication(
    tenantId: "tenant-uuid"
    input: {
      name: "Web App"
      slug: "web-app"
      description: "Main web application"
    }
  ) {
    id
    name
    slug
  }
}

Update Application

graphql
mutation {
  updateApplication(
    id: "app-uuid"
    input: { description: "Updated description" }
  ) {
    id
    description
  }
}

Delete Application

graphql
mutation {
  deleteApplication(id: "app-uuid")
}

Promote Application

Promote/copy an application version to another tenant (environment):

graphql
mutation {
  promoteApplication(
    input: {
      applicationId: "app-uuid"
      targetTenantId: "prod-tenant-uuid"
      slug: "app-slug"
      name: "Application Name"
      version: "1.0.0"
    }
  ) {
    id
    name
    slug
    version
  }
}

Copy Application

Copy an application to another tenant with a new slug:

graphql
mutation {
  copyApplication(
    input: {
      sourceApplicationId: "app-uuid"
      targetTenantId: "new-tenant-uuid"
      slug: "new-app-slug"
      name: "New Application Name"
      version: "1.0.0"
    }
  ) {
    id
    name
    slug
    version
  }
}

Settings Management

Configuration Inheritance

Settings can be defined at three levels: Project → Tenant → Application. Use the create/update mutations to define settings at specific levels, and use the settings query to retrieve the effective merged configuration.

Create Backend Settings

graphql
mutation {
  createBackendSettings(
    input: {
      projectID: "project-uuid" # or tenantID or applicationID
      moduleConfig: {
        EnabledModules: ["auth", "notifications"]
        KeyValuePairs: [
          { Key: "api_timeout", Value: "30" }
          { Key: "max_retries", Value: "3" }
        ]
      }
    }
  ) {
    id
    moduleConfig {
      EnabledModules
      KeyValuePairs {
        Key
        Value
      }
    }
  }
}

Update Backend Settings

graphql
mutation {
  updateBackendSettings(
    id: "backend-settings-uuid"
    input: {
      moduleConfig: {
        EnabledModules: ["auth", "notifications", "analytics"]
        KeyValuePairs: [{ Key: "api_timeout", Value: "60" }]
      }
    }
  ) {
    id
    moduleConfig {
      EnabledModules
    }
  }
}

Delete Backend Settings

graphql
mutation {
  deleteBackendSettings(id: "backend-settings-uuid")
}

Create Frontend Settings

graphql
mutation {
  createFrontendSettings(
    input: {
      applicationID: "app-uuid" # or projectID or tenantID
      moduleConfig: {
        EnabledThemes: ["light", "dark"]
        DefaultTheme: "light"
        EnabledLocales: ["en", "hu", "de"]
        DefaultLocale: "en"
        EnabledModules: ["dashboard", "reports"]
        KeyValuePairs: [{ Key: "show_footer", Value: "true" }]
      }
    }
  ) {
    id
    moduleConfig {
      DefaultTheme
      DefaultLocale
      EnabledThemes
      EnabledLocales
    }
  }
}

Update Frontend Settings

graphql
mutation {
  updateFrontendSettings(
    id: "frontend-settings-uuid"
    input: {
      moduleConfig: {
        DefaultTheme: "dark"
        EnabledModules: ["dashboard", "reports", "analytics"]
      }
    }
  ) {
    id
    moduleConfig {
      DefaultTheme
      EnabledModules
    }
  }
}

Delete Frontend Settings

graphql
mutation {
  deleteFrontendSettings(id: "frontend-settings-uuid")
}

Update Backend Module Configuration

graphql
mutation {
  updateBackendModuleConfig(
    id: "backend-settings-uuid"
    input: {
      EnabledModules: ["module1", "module2"]
      KeyValuePairs: [
        { Key: "feature_flag_1", Value: "true" }
        { Key: "api_timeout", Value: "30" }
      ]
    }
  ) {
    id
    moduleConfig {
      EnabledModules
      KeyValuePairs {
        Key
        Value
      }
    }
  }
}

Update Frontend Module Configuration

graphql
mutation {
  updateFrontendModuleConfig(
    id: "frontend-settings-uuid"
    input: {
      EnabledThemes: ["dark", "light"]
      DefaultTheme: "light"
      EnabledLocales: ["en", "hu"]
      DefaultLocale: "en"
      KeyValuePairs: [{ Key: "show_footer", Value: "true" }]
    }
  ) {
    id
    moduleConfig {
      DefaultTheme
      DefaultLocale
    }
  }
}

Language Pack Management

Create Language Pack

graphql
mutation {
  createLanguagePack(projectId: "project-uuid", input: { name: "en-US" }) {
    id
    name
  }
}

Update Language Pack Content

graphql
mutation {
  updateLanguagePackContent(
    id: "language-pack-uuid"
    input: {
      content: [
        { Key: "welcome", Value: "Welcome" }
        { Key: "login", Value: "Login" }
        { Key: "logout", Value: "Logout" }
      ]
    }
  ) {
    id
    content {
      Key
      Value
    }
  }
}

Endpoint Management

Create Endpoint

graphql
mutation {
  createEndpoint(
    applicationId: "app-uuid"
    input: {
      name: "Webhook Handler"
      description: "Processes incoming webhooks"
      enabled: true
      consumeURL: "/api/webhook"
      url: "https://backend.example.com/webhook"
      authType: Bearer
      inputMessageType: JSON
      outputMessageType: JSON
      logLevel: BASIC
    }
  ) {
    id
    name
    consumeURL
    url
    authType
    inputMessageType
    outputMessageType
    logLevel
  }
}

Field Descriptions:

  • consumeURL - The path pattern that will trigger this endpoint (e.g., /api/webhook)
  • url - The backend URL to forward requests to
  • authType - Authentication method: Basic, Bearer, or None
  • inputMessageType - Expected input format: JSON, XML, or SOAP (optional)
  • outputMessageType - Output format after transformation: JSON, XML, or SOAP (optional)
  • logLevel - ESB logging verbosity: NONE, BASIC, or FULL (default: BASIC)

Update Endpoint

graphql
mutation {
  updateEndpoint(
    id: "endpoint-uuid"
    input: {
      enabled: false
      url: "https://new-backend.example.com/webhook"
      logLevel: FULL
    }
  ) {
    id
    enabled
    url
    logLevel
  }
}

Delete Endpoint

graphql
mutation {
  deleteEndpoint(id: "endpoint-uuid")
}

Trigger Management

Create Trigger

graphql
mutation {
  createTrigger(
    applicationId: "app-uuid"
    input: {
      name: "Daily Report"
      description: "Generates daily report"
      cronExpression: "0 0 * * *"
      runKey: "daily-report"
      enabled: true
    }
  ) {
    id
    name
    cronExpression
    runKey
  }
}

Update Trigger

graphql
mutation {
  updateTrigger(
    id: "trigger-uuid"
    input: { enabled: false, cronExpression: "0 2 * * *" }
  ) {
    id
    enabled
    cronExpression
  }
}

Machine User Management

Create Machine User with Token

graphql
mutation {
  createMachineUserWithCredentials(
    tenantId: "tenant-uuid"
    input: {
      name: "API Service"
      username: "api-service"
      hashedKey: "__GENERATE_TOKEN__"
      enabled: true
    }
  ) {
    generatedToken
    machineUser {
      id
      username
      tokenPrefix
    }
  }
}

Token Generation

Use hashedKey: "__GENERATE_TOKEN__" to auto-generate a Bearer token. The plaintext token is only returned once.

Update Machine User

graphql
mutation {
  updateMachineUser(id: "machine-user-uuid", input: { enabled: false }) {
    id
    enabled
  }
}

Delete Machine User

graphql
mutation {
  deleteMachineUser(id: "machine-user-uuid")
}

Machine User to Endpoint Access

Create Machine User-Endpoint Access

graphql
mutation {
  createMachineUser2Endpoint(
    input: {
      machineUserID: "machine-user-uuid"
      endpointID: "endpoint-uuid"
      enabled: true
    }
  ) {
    id
    enabled
    machineUser {
      username
    }
    endpoint {
      name
    }
  }
}

Update Machine User-Endpoint Access

graphql
mutation {
  updateMachineUser2Endpoint(id: "relation-uuid", input: { enabled: false }) {
    id
    enabled
  }
}

Delete Machine User-Endpoint Access

graphql
mutation {
  deleteMachineUser2Endpoint(id: "relation-uuid")
}

Personal Access Token Management

Create Personal Access Token

graphql
mutation {
  createPersonalAccessToken(
    name: "Production API Token"
    expiresAt: "2025-12-31T23:59:59Z"
  ) {
    token
    personalAccessToken {
      id
      name
      tokenPrefix
      expiresAt
      createdAt
    }
  }
}

One-Time Token Display

The token field contains the full plaintext token and is only returned once. Store it securely.

Revoke Personal Access Token

graphql
mutation {
  revokePersonalAccessToken(id: "pat-uuid") {
    id
    name
    revoked
  }
}

Delete Personal Access Token

graphql
mutation {
  deletePersonalAccessToken(id: "pat-uuid")
}

User Access Management

Simplified User Management

The following mutations provide a simplified interface for user access management. For advanced use cases, low-level mutations (createUser2Project, updateUser2Project, etc.) are also available but generally not recommended for direct use.

Add User to Project

graphql
mutation {
  addUserToProject(
    projectID: "project-uuid"
    userID: "user-uuid"
    role: admin
  ) {
    id
    role
    user {
      username
    }
  }
}

Available Roles: admin, editor, viewer

Update User Project Role

graphql
mutation {
  updateUserProjectRole(id: "relation-uuid", role: viewer) {
    id
    role
  }
}

Remove User from Project

graphql
mutation {
  removeUserFromProject(id: "relation-uuid")
}

Add User to Tenant

graphql
mutation {
  addUserToTenant(tenantID: "tenant-uuid", userID: "user-uuid", role: admin) {
    id
    role
  }
}

Available Roles: admin, editor, viewer

Update User Tenant Role

graphql
mutation {
  updateUserTenantRole(id: "relation-uuid", role: editor) {
    id
    role
  }
}

Remove User from Tenant

graphql
mutation {
  removeUserFromTenant(id: "relation-uuid")
}

Add User to Application

graphql
mutation {
  addUserToApplication(
    applicationID: "app-uuid"
    userID: "user-uuid"
    role: editor
  ) {
    id
    role
  }
}

Available Roles: admin, editor, viewer

Update User Application Role

graphql
mutation {
  updateUserApplicationRole(id: "relation-uuid", role: viewer) {
    id
    role
  }
}

Remove User from Application

graphql
mutation {
  removeUserFromApplication(id: "relation-uuid")
}

Pilet Package Management

Update Pilet Package

graphql
mutation {
  updatePiletPackage(
    projectId: "project-uuid"
    name: "@my-org/my-pilet"
    version: "1.0.0"
    description: "Updated description"
    enabled: true
  ) {
    id
    name
    version
    description
    enabled
  }
}

Pilet Upload

The actual pilet file upload happens via the REST API endpoint POST /pilets/:projectId/:name/:version. This mutation is for metadata updates only.

Enable Pilet Package

graphql
mutation {
  enablePiletPackage(
    projectId: "project-uuid"
    name: "@my-org/my-pilet"
    version: "1.0.0"
  ) {
    id
    enabled
  }
}

Disable Pilet Package

graphql
mutation {
  disablePiletPackage(
    projectId: "project-uuid"
    name: "@my-org/my-pilet"
    version: "1.0.0"
  ) {
    id
    enabled
  }
}

REST API

Machine User Validation

Endpoint: POST /api/validate-machine-user

Description: Validates machine user credentials. Used by the Proxy for authentication.

Authentication: None required (internal use)

Request Body:

json
{
  "username": "machine-user-name",
  "token": "bearer-token-or-password"
}

Response:

json
{
  "valid": true,
  "tenantId": "tenant-uuid",
  "machineUserId": "machine-user-uuid"
}

Check Machine User Auth

Endpoint: GET /api/machine/check

Description: Verifies machine user authentication status.

Authentication: Bearer Token (Machine User)

Response:

json
{
  "authenticated": true,
  "machineUserId": "machine-user-uuid",
  "tenantId": "tenant-uuid"
}

Register Backend

Endpoint: POST /api/machine/register-backend

Description: Registers a backend service for trigger execution callbacks.

Authentication: Bearer Token (Machine User)

Request Body:

json
{
  "name": "Payment Service",
  "callbackUrl": "https://payment.example.com/triggers/callback",
  "description": "Handles payment processing triggers"
}

Response:

json
{
  "id": "backend-uuid",
  "name": "Payment Service",
  "callbackUrl": "https://payment.example.com/triggers/callback",
  "machineUserId": "machine-user-uuid"
}

Validate Proxy Auth

Endpoint: POST /api/validate-proxy-auth

Description: Validates user authentication for the Proxy. Used internally by the Proxy to validate session tokens.

Authentication: None required (internal use)

Request Body:

json
{
  "token": "session-token-or-cookie"
}

Response:

json
{
  "valid": true,
  "userId": "user-uuid",
  "username": "user@example.com"
}

Frontend Configuration

Endpoint: GET /api/frontend-config/:application_id

Description: Retrieves frontend configuration for an application, including theme, locale, and enabled modules.

Authentication: None required (public endpoint, used by Proxy)

Response:

json
{
  "applicationId": "app-uuid",
  "moduleConfig": {
    "EnabledModules": ["module1", "module2"],
    "EnabledThemes": ["light", "dark"],
    "DefaultTheme": "light",
    "EnabledLocales": ["en", "hu"],
    "DefaultLocale": "en",
    "KeyValuePairs": [{ "Key": "feature_flag", "Value": "true" }]
  }
}

Pilet Feed

Endpoint: GET /pilet-feed/:applicationId

Description: Returns the Piral-compatible pilet feed for an application. This endpoint is used by the frontend to discover and load pilets (microfrontends).

Authentication: None required (public endpoint)

Response:

json
{
  "items": [
    {
      "name": "@my-org/my-pilet",
      "version": "1.0.0",
      "link": "https://manager.example.com/pilets/project-uuid/@my-org/my-pilet/1.0.0",
      "hash": "sha256-abcd1234...",
      "spec": "v2"
    }
  ]
}

Pilet Package Management

List Pilets

Endpoint: GET /pilets/:projectId

Description: Lists all pilet packages for a project.

Authentication: Bearer Token (Personal Access Token or User Session)

Query Parameters:

  • enabled (optional): Filter by enabled status (true/false)

Response:

json
{
  "packages": [
    {
      "id": "pilet-uuid",
      "name": "@my-org/my-pilet",
      "version": "1.0.0",
      "description": "My pilet description",
      "size": 123456,
      "hash": "sha256-abcd1234...",
      "enabled": true,
      "createdAt": "2024-01-01T00:00:00Z",
      "updatedAt": "2024-01-02T00:00:00Z"
    }
  ],
  "count": 1
}

Upload Pilet

Endpoint: POST /pilets/:projectId/:name/:version

Description: Uploads a new pilet package or updates an existing one.

Authentication: Bearer Token (Personal Access Token or User Session)

Request:

  • Content-Type: multipart/form-data
  • File field: file (the .tgz pilet package)
  • Optional field: description (string)

Response:

json
{
  "id": "pilet-uuid",
  "name": "@my-org/my-pilet",
  "version": "1.0.0",
  "size": 123456,
  "hash": "sha256-abcd1234...",
  "enabled": true
}

Download Pilet

Endpoint: GET /pilets/:projectId/:name/:version

Description: Downloads a pilet package file.

Authentication: Bearer Token (Personal Access Token or User Session)

Response: Binary .tgz file

Headers:

  • Content-Type: application/gzip
  • Content-Disposition: attachment; filename="<name>-<version>.tgz"

Delete Pilet

Endpoint: DELETE /pilets/:projectId/:name/:version

Description: Deletes a pilet package.

Authentication: Bearer Token (Personal Access Token or User Session)

Response:

json
{
  "success": true
}

ESB (Enterprise Service Bus) Endpoints

Endpoint: ANY /esb/:applicationId/*endpointPath

Description: Routes requests to registered backend endpoints through the ESB. Supports all HTTP methods (GET, POST, PUT, DELETE, etc.).

Authentication: Handled by Proxy (expects X-User-ID header)

Headers:

  • X-User-ID: User ID (set by Proxy)
  • X-Application-ID: Application ID (optional)
  • X-Tenant-ID: Tenant ID (optional)

Example:

bash
# Request to ESB
GET /esb/app-uuid/api/users/123

# Routed to configured backend endpoint
# Based on endpoint configuration with consumeURL matching "/api/users/*"

Error Handling

GraphQL Errors

GraphQL errors follow this structure:

json
{
  "errors": [
    {
      "message": "Project not found",
      "path": ["project"],
      "extensions": {
        "code": "NOT_FOUND"
      }
    }
  ],
  "data": null
}

Common Error Codes:

  • UNAUTHENTICATED - Missing or invalid authentication
  • FORBIDDEN - Insufficient permissions
  • NOT_FOUND - Resource not found
  • BAD_USER_INPUT - Invalid input data
  • INTERNAL_SERVER_ERROR - Server error

REST API Errors

REST endpoints return HTTP status codes with error details:

json
{
  "error": "Invalid credentials",
  "code": "INVALID_CREDENTIALS",
  "status": 401
}

Common HTTP Status Codes:

  • 200 - Success
  • 400 - Bad Request
  • 401 - Unauthorized
  • 403 - Forbidden
  • 404 - Not Found
  • 500 - Internal Server Error

Rate Limiting

Currently, there are no hard rate limits enforced. For production deployments, it's recommended to implement rate limiting at the reverse proxy level (e.g., using Caddy or nginx).


Best Practices

1. Use Filtering and Pagination

Always use pagination for list queries to avoid performance issues:

graphql
query {
  projects(
    filters: [{ field: "name", value: "prod" }]
    order: { field: "created_at", direction: DESC }
    pagination: { limit: 20, offset: 0 }
  ) {
    id
    name
  }
}

2. Request Only Required Fields

GraphQL allows you to request only the fields you need:

graphql
query {
  project(slug: "my-project") {
    id
    name
    # Don't fetch relations unless needed
  }
}

3. Secure Token Storage

  • Never commit tokens to version control
  • Use environment variables or secret management systems
  • Rotate tokens regularly
  • Use expiration dates for PATs

4. Handle Errors Gracefully

Always check for errors in GraphQL responses:

javascript
const response = await fetch("/query", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${token}`,
  },
  body: JSON.stringify({ query, variables }),
});

const { data, errors } = await response.json();

if (errors) {
  // Handle errors
  console.error("GraphQL errors:", errors);
}

5. Use Machine Users for Services

For backend services and integrations, always use machine users instead of personal access tokens. Machine users provide:

  • Tenant-scoped access
  • No expiration (unless disabled)
  • Better audit trails
  • Service account semantics

Examples

Complete Project Setup

graphql
# 1. Create project
mutation {
  createProject(input: { name: "E-commerce Platform", slug: "ecommerce" }) {
    id
  }
}

# 2. Create tenant
mutation {
  createTenant(
    projectId: "project-uuid"
    input: { name: "Store A", slug: "store-a", type: run }
  ) {
    id
  }
}

# 3. Create application
mutation {
  createApplication(
    tenantId: "tenant-uuid"
    input: {
      name: "Storefront"
      slug: "storefront"
      description: "Customer-facing web application"
    }
  ) {
    id
  }
}

# 4. Configure settings
mutation {
  updateFrontendModuleConfig(
    id: "settings-uuid"
    input: {
      EnabledThemes: ["light", "dark"]
      DefaultTheme: "light"
      DefaultLocale: "en"
    }
  ) {
    id
  }
}

Trigger-Based Workflow

graphql
# 1. Create backend endpoint
mutation {
  createEndpoint(
    applicationId: "app-uuid"
    input: {
      name: "Order Processor"
      description: "Processes orders"
      consumeURL: "/api/orders/process"
      url: "https://backend.example.com/process-orders"
      enabled: true
      authType: Bearer
    }
  ) {
    id
  }
}

# 2. Create trigger
mutation {
  createTrigger(
    applicationId: "app-uuid"
    input: {
      name: "Hourly Order Processing"
      description: "Processes orders hourly"
      cronExpression: "0 * * * *"
      runKey: "hourly-orders"
      enabled: true
    }
  ) {
    id
  }
}

# 3. Register backend for callbacks
# (REST API call with machine user token)
POST /api/machine/register-backend
{
  "name": "Order Service",
  "callbackUrl": "https://backend.example.com/triggers/callback"
}

API Versioning

The GraphQL API is unversioned but follows these principles:

  • Additive changes - New fields and types are added without breaking existing queries
  • Deprecation - Fields are marked @deprecated before removal
  • No breaking changes - Existing fields maintain their contracts

For REST endpoints, the current version is v1 (implicit). Future versions will be explicitly versioned in the URL path.