PayKitBeta

Catalog

Read the project catalog: plans, their versions (prices), and the features each version grants. Catalog is normally configured in the dashboard; a client app mostly needs to read it (to render pricing) and the resulting planVersionId to subscribe against.

GET/v1/clients/{clientId}/projects/{projectId}/catalog

Get the full catalog

catalog.read

One call that assembles every plan with its versions, each version’s entitlements, and the project feature dictionary, as a single JSON document. Ideal for seeding a pricing page or app config.

Path parameters

clientIdstringYour PayKit client id.
projectIdstringThe project (environment).

Query parameters

includeArchivedstringSet to "true" to include archived plans. Omitted/false returns only live plans.

Read-only. A management-scoped API key qualifies (management grants catalog.read); entitlements_read does not.

To subscribe a customer, use versions[0].id as the planVersionId in Create a subscription.

Check catalog.truncated before treating a list as the whole catalogue; a true flag means that list is a prefix.

This document is also the catalog import format (file version 2). A version 1 file is refused: add-ons changed shape, so export again rather than hand-editing an old file.

curl -X GET "https://api.paykit.co.za/v1/clients/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6/projects/f6e5d4c3b2a1908172635445362718a9/catalog" \
  -H "Authorization: Bearer YOUR_API_KEY"
200 OK
{
  "catalog": {
    "features": [
      {
        "id": "f_9a8b7c",
        "code": "seats",
        "name": "Team seats",
        "description": "Included user seats.",
        "kind": "limit"
      },
      {
        "id": "f_1c2d3e",
        "code": "sso",
        "name": "SSO",
        "description": "SAML single sign-on.",
        "kind": "boolean"
      }
    ],
    "plans": [
      {
        "id": "pl_11aa22",
        "code": "pro",
        "name": "Pro",
        "displayName": "Pro",
        "tagline": "For growing teams",
        "description": "Everything you need to scale.",
        "isArchived": false,
        "createdAt": "2026-06-01T09:00:00Z",
        "versions": [
          {
            "id": "pv_9a8b",
            "version": 2,
            "amountMinor": "49900",
            "currency": "ZAR",
            "billingInterval": "month",
            "intervalCount": 1,
            "trialDays": 14,
            "billingRules": {},
            "effectiveFrom": "2026-07-01T00:00:00Z",
            "createdAt": "2026-07-01T09:00:00Z",
            "entitlements": [
              {
                "featureId": "f_9a8b7c",
                "featureCode": "seats",
                "kind": "limit",
                "boolValue": null,
                "limitValue": "10"
              },
              {
                "featureId": "f_1c2d3e",
                "featureCode": "sso",
                "kind": "boolean",
                "boolValue": true,
                "limitValue": null
              }
            ]
          }
        ]
      }
    ],
    "addons": [
      {
        "id": "ao_5f6a7b",
        "code": "game-zelda",
        "name": "Zelda",
        "displayName": "The Legend of Zelda",
        "tagline": "Adventure, 1986",
        "description": "The one that started it.",
        "isArchived": false,
        "createdAt": "2026-07-30T09:00:00Z",
        "currentVersion": {
          "id": "av_3c4d",
          "pricingType": "fixed",
          "amountMinor": "4900",
          "currency": "ZAR",
          "billingMode": "one_time",
          "durationDays": null,
          "boundToPeriod": false,
          "packQuantity": null,
          "expiresWithPeriod": false,
          "entitlements": []
        }
      },
      {
        "id": "ao_7c8d9e",
        "code": "team-pack",
        "name": "Team pack",
        "displayName": "Team pack",
        "tagline": "Five more seats, and SSO",
        "description": "For a team that outgrew the plan.",
        "isArchived": false,
        "createdAt": "2026-08-01T09:00:00Z",
        "currentVersion": {
          "id": "av_5e6f",
          "pricingType": "fixed",
          "amountMinor": "9900",
          "currency": "ZAR",
          "billingMode": "recurring",
          "durationDays": null,
          "boundToPeriod": true,
          "packQuantity": null,
          "expiresWithPeriod": false,
          "entitlements": [
            {
              "featureId": "f_9a8b7c",
              "featureCode": "seats",
              "kind": "limit",
              "boolValue": null,
              "limitValue": "5"
            },
            {
              "featureId": "f_1c2d3e",
              "featureCode": "sso",
              "kind": "boolean",
              "boolValue": true,
              "limitValue": null
            }
          ]
        }
      }
    ],
    "truncated": {
      "plans": false,
      "planVersions": false,
      "addons": false
    }
  }
}
GET/v1/projects/{projectId}/catalog

Get the public catalog (pricing)

no auth

Unauthenticated pricing read for a public page: no client id, no API key. Returns only live plans and live add-ons with display-safe fields (no internal policy, no internal ids). Cacheable; open CORS, so it is safe to call from a browser before anyone signs up.

Path parameters

projectIdstringThe project (environment) id. Not a secret: it is meant to ship in front-end JavaScript.

No auth; safe to call straight from a browser or a CDN to render pricing before signup.

Live projects only. A project still in test mode returns the same 404 as an id that belongs to no project, so a project id cannot be used to read an unlaunched catalogue.

Live (non-archived) plans and add-ons only; omits internal policy (billingRules) and internal ids. Both catalog reads list the same add-ons.

Read a price here, then buy with addOnCode and quantity only. The purchase endpoint ignores any amount you send and re-reads the price from the catalog.

A limit entitlement on an add-on is the raise per unit of quantity: buying 2 of a "+5 seats" add-on adds 10 seats. A boolean entitlement is simply on, and does not scale.

Check catalog.truncated before treating a list as the whole catalogue; a true flag means that list is a prefix.

Catalog is configured in the PayKit dashboard or through a management API key, never written via this route.

curl -X GET "https://api.paykit.co.za/v1/projects/f6e5d4c3b2a1908172635445362718a9/catalog"
200 OK
{
  "catalog": {
    "features": [
      {
        "code": "seats",
        "name": "Team seats",
        "description": "Included user seats.",
        "kind": "limit"
      }
    ],
    "plans": [
      {
        "code": "pro",
        "name": "Pro",
        "displayName": "Pro",
        "tagline": "For growing teams",
        "description": "Everything you need to scale.",
        "versions": [
          {
            "id": "pv_9a8b",
            "version": 2,
            "amountMinor": "49900",
            "currency": "ZAR",
            "billingInterval": "month",
            "intervalCount": 1,
            "trialDays": 14,
            "entitlements": [
              {
                "featureCode": "seats",
                "kind": "limit",
                "boolValue": null,
                "limitValue": "10"
              }
            ]
          }
        ]
      }
    ],
    "addons": [
      {
        "code": "game-zelda",
        "name": "Zelda",
        "displayName": "The Legend of Zelda",
        "tagline": "Adventure, 1986",
        "description": "The one that started it.",
        "currentVersion": {
          "amountMinor": "4900",
          "currency": "ZAR",
          "billingMode": "one_time",
          "durationDays": null,
          "boundToPeriod": false,
          "packQuantity": null,
          "expiresWithPeriod": false,
          "entitlements": []
        }
      },
      {
        "code": "team-pack",
        "name": "Team pack",
        "displayName": "Team pack",
        "tagline": "Five more seats, and SSO",
        "description": "For a team that outgrew the plan.",
        "currentVersion": {
          "amountMinor": "9900",
          "currency": "ZAR",
          "billingMode": "recurring",
          "durationDays": null,
          "boundToPeriod": true,
          "packQuantity": null,
          "expiresWithPeriod": false,
          "entitlements": [
            {
              "featureCode": "seats",
              "kind": "limit",
              "boolValue": null,
              "limitValue": "5"
            },
            {
              "featureCode": "sso",
              "kind": "boolean",
              "boolValue": true,
              "limitValue": null
            }
          ]
        }
      }
    ],
    "truncated": {
      "plans": false,
      "planVersions": false,
      "addons": false
    }
  }
}