{
  "apiVersion": "2026-11-01",
  "manifestVersion": 1,
  "authentication": "Every /api/integration call carries X-Manajemin-Key: <key_prefix>.<secret>. The key is issued once in the developer portal.",
  "webhook": {
    "headers": [
      "X-Manajemin-Event",
      "X-Manajemin-Delivery",
      "X-Manajemin-Tenant",
      "X-Manajemin-Entity",
      "X-Manajemin-Timestamp",
      "X-Manajemin-Signature",
      "X-Manajemin-Api-Version"
    ],
    "signature": "X-Manajemin-Signature is `t=<unix seconds>,v1=<hex>` where hex = HMAC-SHA256(webhook secret, `<t>.<raw request body>`). For 24 hours after a webhook secret is replaced there is one v1 per secret (`t=<t>,v1=<new>,v1=<old>`); accept if any v1 matches. Reject if the timestamp is more than 300 seconds old, then compare in constant time. Deduplicate on X-Manajemin-Delivery."
  },
  "events": [
    {
      "type": "entity.created",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.trialing",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.active",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.past_due",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.grace",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.suspended",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.cancelled",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "subscription.plan_changed",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "invoice.issued",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "invoice.paid",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "member.suspended",
      "audience": "entity",
      "defaultOn": true,
      "payload": [
        "member_id",
        "user_id",
        "email",
        "role"
      ]
    },
    {
      "type": "member.reactivated",
      "audience": "entity",
      "defaultOn": true,
      "payload": [
        "member_id",
        "user_id",
        "email",
        "role"
      ]
    },
    {
      "type": "member.removal_requested",
      "audience": "entity",
      "defaultOn": true,
      "payload": [
        "member_id",
        "user_id",
        "email",
        "transfer_to_member_id"
      ]
    },
    {
      "type": "member.removed",
      "audience": "entity",
      "defaultOn": true,
      "payload": [
        "member_id",
        "user_id",
        "email"
      ]
    },
    {
      "type": "app.install",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "member.session_revoked",
      "audience": "entity",
      "defaultOn": true,
      "payload": [
        "user_id"
      ]
    },
    {
      "type": "app.uninstall_requested",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "app.test_event",
      "audience": "entity",
      "defaultOn": true
    },
    {
      "type": "tenant.provisioned",
      "audience": "app",
      "defaultOn": false
    },
    {
      "type": "client.lead.created",
      "audience": "app",
      "defaultOn": false
    },
    {
      "type": "tenant.closed",
      "audience": "tenant",
      "defaultOn": false
    },
    {
      "type": "tenant.erased",
      "audience": "tenant",
      "defaultOn": false
    },
    {
      "type": "subject.erasure_requested",
      "audience": "tenant",
      "defaultOn": false,
      "payload": [
        "request_id",
        "email",
        "user_id",
        "member_id",
        "reason"
      ]
    },
    {
      "type": "guest.grant.created",
      "audience": "entity",
      "defaultOn": false,
      "payload": [
        "guest_grant_id",
        "email"
      ]
    },
    {
      "type": "guest.grant.revoked",
      "audience": "entity",
      "defaultOn": false,
      "payload": [
        "guest_grant_id",
        "revoked_at"
      ]
    },
    {
      "type": "app.peer_removed",
      "audience": "entity",
      "defaultOn": false,
      "payload": [
        "peer_app_id",
        "peer_name"
      ]
    },
    {
      "type": "app.export_requested",
      "audience": "entity",
      "defaultOn": false,
      "payload": [
        "export_id",
        "reason"
      ]
    }
  ],
  "scopes": [
    {
      "scope": "snapshot:read",
      "allows": "GET /api/integration/snapshot: read the current tier snapshot of a workspace the app is installed on.",
      "byDefault": true
    },
    {
      "scope": "usage:write",
      "allows": "POST /api/integration/usage: report usage deltas for the app's declared metrics.",
      "byDefault": true
    },
    {
      "scope": "provisioning:ack",
      "allows": "POST /api/integration/ack and /uninstall-ack, and /ack-removal: acknowledge an install, an uninstall or a member removal.",
      "byDefault": true
    },
    {
      "scope": "guest-grants:write",
      "allows": "POST /api/integration/guest-grants: create a guest grant (the app must support guest access).",
      "byDefault": true
    },
    {
      "scope": "sso:exchange",
      "allows": "POST /api/integration/exchange: redeem the one-time SSO code for the signed-in user's claims.",
      "byDefault": true
    },
    {
      "scope": "members:read",
      "allows": "GET /api/integration/members: read the member directory of a workspace the app is installed on.",
      "byDefault": false
    },
    {
      "scope": "audit:write",
      "allows": "POST /api/integration/audit: write an entry into the organisation's tamper-evident activity log.",
      "byDefault": false
    },
    {
      "scope": "notify:send",
      "allows": "POST /api/integration/notify: send an email to a member of the workspace through the platform.",
      "byDefault": false
    },
    {
      "scope": "ai:invoke",
      "allows": "POST /api/integration/ai: ask the platform's model on behalf of a member of the workspace, metered against the organisation's AI budget. Also required to offer tools to Jemi (the manifest's `tools`), which an admin must switch on.",
      "byDefault": false
    },
    {
      "scope": "events:publish",
      "allows": "POST /api/integration/events: hand an event your manifest declares (`appEvents.publishes`) to the other apps installed on the same workspace that subscribed to it and whose admin consented.",
      "byDefault": false
    },
    {
      "scope": "telemetry:write",
      "allows": "POST /api/integration/telemetry: record which of your app's features were used on a workspace (a feature name and, optionally, the member who used it). Counts only: it carries no content, and the platform shows it as adoption under module `app:<your app id>`.",
      "byDefault": false
    },
    {
      "scope": "files:store",
      "allows": "POST /api/integration/files and its siblings: store a file for a workspace in the platform's private storage, counted against the organisation's storage quota. Upload and download go straight to storage through short-lived links; the app can only reach its own files. Deleted with the install.",
      "byDefault": false
    }
  ]
}
