SeloraXDEVELOPERS

Developer Apps API

Developer Apps API

Base path: /api/v1/apps

All endpoints require authentication via Authorization: Bearer <accessToken>.

List My Apps

GET /api/v1/apps?page=1&limit=20&status=active&listed=true
ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Results per page (max 100)
statusstring--Filter: active or inactive
listedboolean--Filter by marketplace listing status

Response (200):

{
  "status": 200,
  "message": "Apps fetched",
  "data": {
    "items": [
      {
        "app_id": 2,
        "app_type": "platform",
        "name": "SeloraX Messaging",
        "slug": "selorax-messaging",
        "icon": "https://cdn.example.com/icon.png",
        "short_description": "Automated SMS for order updates",
        "is_listed": 1,
        "is_active": 1,
        "created_at": "2026-01-15T08:30:00.000Z",
        "updated_at": "2026-02-28T10:00:00.000Z"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}

Get App Details

GET /api/v1/apps/:appId

Response (200):

{
  "status": 200,
  "message": "App fetched",
  "data": {
    "app_id": 2,
    "app_type": "platform",
    "name": "SeloraX Messaging",
    "slug": "selorax-messaging",
    "icon": "https://cdn.example.com/icon.png",
    "screenshots": ["https://cdn.example.com/shot-1.png"],
    "description": "Full description of the app...",
    "short_description": "Automated SMS for order updates",
    "homepage_url": "https://messaging.selorax.com",
    "app_url": "https://messaging.selorax.com/embed",
    "setup_url": null,
    "webhook_url": "https://api.messaging.selorax.com/api/messaging/oauth",
    "webhook_receive_url": "https://api.messaging.selorax.com/api/messaging/webhooks",
    "webhook_topics": ["order.status_changed"],
    "redirect_urls": ["https://messaging.selorax.com/oauth/callback"],
    "requested_scopes": ["read:orders", "read:customers", "read:store", "billing"],
    "developer_name": "SeloraX Team",
    "developer_email": "[email protected]",
    "pricing_type": "usage",
    "pricing_amount": 0,
    "fee_payer": "developer",
    "category": "messaging",
    "metadata": null,
    "is_listed": 1,
    "is_active": 1,
    "client_id": "sx_app_1b16e193a28d2640d2d9734dbf4907e8",
    "created_by": 42,
    "created_at": "2026-01-15T08:30:00.000Z",
    "updated_at": "2026-02-28T10:00:00.000Z"
  }
}

Errors:

  • 404 APP_NOT_FOUND — App not found or not owned by you

Create App

POST /api/v1/apps
Content-Type: application/json

Request Body:

{
  "name": "My Custom App",
  "slug": "my-custom-app",
  "redirect_urls": ["https://example.com/oauth/callback"],
  "requested_scopes": ["read:orders", "read:products", "billing"],
  "description": "A detailed description of what the app does",
  "short_description": "Brief marketplace summary",
  "icon": "https://cdn.example.com/icon.png",
  "screenshots": ["https://cdn.example.com/shot-1.png"],
  "homepage_url": "https://example.com",
  "app_url": "https://example.com/embed",
  "setup_url": "https://example.com/setup",
  "webhook_url": "https://api.example.com/oauth",
  "webhook_receive_url": "https://api.example.com/webhooks",
  "webhook_topics": ["order.status_changed", "order.created"],
  "developer_name": "Acme Labs",
  "developer_email": "[email protected]",
  "pricing_type": "subscription",
  "pricing_amount": 499,
  "fee_payer": "developer",
  "category": "analytics",
  "metadata": { "version": "1.0" }
}

Required fields: name, redirect_urls (min 1), requested_scopes (min 1)

Validation:

  • name: 3-255 characters
  • slug: 3-255 chars, lowercase letters, numbers, dashes only
  • description: max 8000 characters
  • short_description: max 500 characters
  • screenshots: max 10 URLs
  • fee_payer: "developer" or "merchant"

Response (201):

{
  "status": 201,
  "message": "App created",
  "data": {
    "app_id": 5,
    "name": "My Custom App",
    "slug": "my-custom-app",
    "clientId": "sx_app_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "clientSecret": "sx_secret_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "sessionSigningKey": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
  }
}

Save your credentials

The clientSecret and sessionSigningKey are shown only once at creation time. Store them securely — they cannot be retrieved later. If lost, use the rotation endpoints to generate new ones.

Errors:

  • 409 SLUG_EXISTS — Slug already in use
  • 409 DUPLICATE_FIELD — Unique constraint violation

Update App Profile

PATCH /api/v1/apps/:appId
Content-Type: application/json

All fields are optional. Only include fields you want to change:

{
  "icon": "https://cdn.example.com/new-icon.png",
  "screenshots": ["https://cdn.example.com/shot-1.png", "https://cdn.example.com/shot-2.png"],
  "short_description": "Updated description",
  "developer_name": "Acme Labs v2"
}

Response (200):

{
  "status": 200,
  "message": "App updated",
  "data": {
    "app_id": 5,
    "name": "My Custom App",
    "slug": "my-custom-app",
    "icon": "https://cdn.example.com/new-icon.png",
    "screenshots": ["https://cdn.example.com/shot-1.png", "https://cdn.example.com/shot-2.png"],
    "short_description": "Updated description",
    "updated_at": "2026-02-28T12:00:00.000Z"
  }
}

Delete App

DELETE /api/v1/apps/:appId

Soft-deletes the app (sets deleted_at, marks inactive).

Response (200):

{
  "status": 200,
  "message": "App deleted",
  "data": { "app_id": 5 }
}

Update Listing Status

Controls marketplace visibility. When is_listed is true, merchants can discover and install your app from the marketplace.

PATCH /api/v1/apps/:appId/listing
Content-Type: application/json
{
  "is_listed": true
}

Response (200):

{
  "status": 200,
  "message": "App listing updated",
  "data": { "app_id": 5, "is_listed": 1 }
}

Update Active Status

Controls whether the app functions. When is_active is false, existing installations stop working.

PATCH /api/v1/apps/:appId/status
Content-Type: application/json
{
  "is_active": true
}

Response (200):

{
  "status": 200,
  "message": "App status updated",
  "data": { "app_id": 5, "is_active": 1 }
}

Rotate Client Secret

Generates a new client secret. The old secret is immediately invalidated.

POST /api/v1/apps/:appId/rotate-secret

Response (200):

{
  "status": 200,
  "message": "Client secret rotated",
  "data": {
    "app_id": 5,
    "client_secret": "sx_secret_new..."
  }
}

After rotating, update the secret in all your backend services immediately. The old secret will no longer work for token exchange or client credential authentication.

Regenerate Signing Key

Generates a new session signing key. Existing session tokens signed with the old key become invalid.

POST /api/v1/apps/:appId/regenerate-signing-key

Response (200):

{
  "status": 200,
  "message": "Session signing key regenerated",
  "data": {
    "app_id": 5,
    "session_signing_key": "a1b2c3d4..."
  }
}

App Settings

Get all settings grouped by category:

GET /api/v1/apps/:appId/settings

Response (200):

{
  "status": 200,
  "message": "Settings fetched",
  "data": {
    "oauth": {
      "redirect_urls": ["https://example.com/oauth/callback"],
      "requested_scopes": ["read:orders", "billing"]
    },
    "webhooks": {
      "webhook_receive_url": "https://api.example.com/webhooks",
      "webhook_topics": ["order.status_changed"]
    },
    "embed": {
      "app_url": "https://example.com/embed",
      "setup_url": null
    },
    "billing": {
      "pricing_type": "subscription",
      "pricing_amount": 499,
      "fee_payer": "developer"
    },
    "developer": {
      "developer_name": "Acme Labs",
      "developer_email": "[email protected]"
    }
  }
}

Update Settings by Category

Each settings group has its own PATCH endpoint:

PATCH /api/v1/apps/:appId/settings/oauth
PATCH /api/v1/apps/:appId/settings/webhooks
PATCH /api/v1/apps/:appId/settings/embed
PATCH /api/v1/apps/:appId/settings/billing
PATCH /api/v1/apps/:appId/settings/developer

Example — update webhook settings:

{
  "webhook_receive_url": "https://api.example.com/webhooks/v2",
  "webhook_topics": ["order.status_changed", "order.created"]
}

List Installations

View all stores that have installed your app:

GET /api/v1/apps/:appId/installations?page=1&limit=20&status=active
ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Results per page (max 100)
statusstring--Filter: active, uninstalled, etc.

Response (200):

{
  "status": 200,
  "message": "Installations fetched",
  "data": {
    "items": [
      {
        "installation_id": 2,
        "store_id": 22,
        "status": "active",
        "granted_scopes": ["read:orders", "read:customers", "read:store", "billing"],
        "token_expires_at": "2026-02-28T22:00:00.000Z",
        "last_used_at": "2026-02-28T10:30:00.000Z",
        "request_count": 1547,
        "created_at": "2026-01-20T09:00:00.000Z",
        "updated_at": "2026-02-28T10:30:00.000Z"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}

Billing Charges

View charges created by your app across all stores:

GET /api/v1/apps/:appId/billing/charges?page=1&limit=20&status=completed
ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Results per page (max 100)
statusstring--Filter by charge status

Response (200):

{
  "status": 200,
  "message": "Charges fetched",
  "data": {
    "items": [
      {
        "charge_id": 8,
        "store_id": 22,
        "installation_id": 2,
        "charge_type": "wallet_topup",
        "name": "Wallet Top-up",
        "amount": 500.00,
        "base_amount": 500.00,
        "currency": "BDT",
        "fee_payer": "developer",
        "commission_rate": 0.1,
        "platform_amount": 50.00,
        "gateway_fee_rate": 0.025,
        "gateway_fee_amount": 12.50,
        "developer_amount": 437.50,
        "status": "completed",
        "created_at": "2026-02-20T09:00:00.000Z",
        "activated_at": "2026-02-20T09:05:00.000Z"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}

Revenue Ledger

View the developer revenue ledger (platform commission breakdown):

GET /api/v1/apps/:appId/billing/revenue?page=1&limit=20

Response (200):

{
  "status": 200,
  "message": "Revenue fetched",
  "data": {
    "items": [
      {
        "ledger_id": "1",
        "app_id": 2,
        "charge_id": 8,
        "from_wallet_amount": "500.00",
        "to_wallet_amount": "400.00",
        "amount": "500.00",
        "type": "topup",
        "description": "Wallet Top-up",
        "created_at": "2026-02-20T09:05:00.000Z"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}

Developer Balance

Check your available balance (earnings minus payouts):

GET /api/v1/apps/:appId/billing/balance

Response (200):

{
  "status": 200,
  "message": "Balance fetched",
  "data": {
    "app_id": 2,
    "total_earned": "1250.00",
    "total_paid_out": "0.00",
    "available_balance": "1250.00",
    "currency": "BDT",
    "updated_at": "2026-02-28T10:00:00.000Z"
  }
}

App Overview Dashboard

Get aggregated stats for your app:

GET /api/v1/apps/:appId/overview

Response (200):

{
  "status": 200,
  "message": "App overview fetched",
  "data": {
    "installations": {
      "active": 12,
      "total": 15
    },
    "charges": {
      "count": 47,
      "total_amount": "23500.00",
      "total_developer_amount": "18800.00"
    },
    "webhooks": {
      "active_subscriptions": 12,
      "delivered_7d": 342,
      "failed_7d": 3
    },
    "recent_activity": {
      "latest_installation": {
        "installation_id": 15,
        "store_id": 45,
        "status": "active",
        "created_at": "2026-02-27T14:30:00.000Z"
      },
      "latest_charge": {
        "charge_id": 47,
        "name": "Wallet Top-up",
        "amount": 500.00,
        "status": "completed",
        "created_at": "2026-02-28T09:00:00.000Z"
      },
      "latest_delivery": {
        "delivery_id": "342",
        "event_topic": "order.status_changed",
        "status": "success",
        "created_at": "2026-02-28T10:15:00.000Z"
      }
    }
  }
}