DEVELOPERS · PLUGIN PLATFORM

Extend OnGravy with plugins

OnGravy's plugin platform is the modern successor to Tally's TDL: a declarative manifest, a closed permission set, and a sandboxed runtime that audits every call. Ship voucher hooks, custom reports, dashboard widgets, exports, and webhooks without forking the codebase.

Plugin marketplace launches Q2 2027. Today plugins are invite-only review — email plugins@ongravy.com with your manifest and we'll get you into the early-access cohort.

How a plugin works

  1. 1
    Manifest
    A plain object — id, version, name, author, description, category, entrypoint, permissions, optional jurisdictions. This is the trust boundary. Whatever the manifest doesn't declare, the runtime literally won't let you call.
  2. 2
    Registry
    Each plugin module calls registerPlugin(manifest, factory) at import time. The registry validates the id (regex), the version (SemVer), and every permission (closed set). Bad manifests fail fast at boot, not at runtime.
  3. 3
    Sandbox
    On invocation, the runtime builds a context object that contains only the methods your manifest requested. Asked for read:vouchers but not write:vouchers? ctx.writeVoucherTags is undefined. There's no monkey-patching around this.
  4. 4
    Audit trail
    Every invocation — success, denial, or error — appends one event to activity_events with the plugin id, version, caller user/business, jurisdiction, outcome, and duration. Admins can revoke a plugin's permissions with a single click and watch the audit log confirm it.

A worked example

Reproduced verbatim from plugins/sample-voucher-tagger/index.ts. This plugin auto-applies a high-value tag to every voucher of ₹50,000 or more.

import { registerPlugin } from '@/lib/plugins/registry';
import type { PluginManifest } from '@/lib/plugins/types';

const HIGH_VALUE_THRESHOLD_PAISE = 50_000 * 100;  // 50_00_000

const manifest: PluginManifest = {
  id:          'sample-voucher-tagger',
  version:     '1.0.0',
  name:        'High-Value Voucher Tagger',
  author:      'OnGravy',
  description: 'Auto-applies the "high-value" tag to vouchers worth ₹50K or more.',
  category:    'voucher',
  entrypoint:  'plugins/sample-voucher-tagger/index.ts',
  permissions: ['read:vouchers', 'write:vouchers'],
};

registerPlugin(manifest, () => async (ctx) => {
  if (!ctx.readVouchers || !ctx.writeVoucherTags) {
    return { ok: false, error: 'missing required permissions' };
  }
  const candidates = await ctx.readVouchers({
    minAmountPaise: HIGH_VALUE_THRESHOLD_PAISE,
  });
  const tagged: string[] = [];
  for (const v of candidates) {
    if (v.tags.includes('high-value')) continue;
    await ctx.writeVoucherTags(v.id, [...v.tags, 'high-value']);
    tagged.push(v.id);
  }
  return { ok: true, data: { taggedCount: tagged.length, tagged } };
});

Permission matrix

The complete, current set. 9 permissions in API v1. Adding a new permission is a host change — plugins cannot extend the set on their own.

PermissionCapabilityRisk
read:vouchersList vouchers + filters (type, amount range).low
write:vouchersAppend cost-centre tags to a voucher.medium
read:partiesRead the customer/supplier ledger.low
write:partiesCreate or update party records.medium
read:itemsRead the inventory item master.low
write:itemsCreate or update item-master records.medium
read:reportsPull canned reports (P&L, BS, GST) read-only.low
send:webhookPOST to an outbound URL with a JSON payload.high
render:dashboard-widgetRender a tile on the home dashboard.low

Submit a plugin for review

Send us your manifest and source. We'll review for security and behaviour, then load it for your business inside one week.

Email plugins@ongravy.com

FAQ

How do I distribute a plugin?
Today: send the source + manifest to plugins@ongravy.com. We review for security and behaviour, then load it as a first-party module. The Q2 2027 marketplace will let CAs and ISVs upload directly.
What does the review process look like?
We check the manifest (permissions match behaviour), read the entrypoint for unsafe patterns, run our sandbox harness, and pilot the plugin on a sandbox business for one week. Most reviews close in 5 business days.
What can I charge for a plugin?
Anything. Today commercials are bilateral — you set the price, we collect via OnGravy billing and take a 15% platform fee. The marketplace will introduce a self-serve pricing surface.
How does the lifecycle work?
Plugins are versioned (SemVer). A new version is reviewed before it goes live. Businesses can pin to a specific version; admins see a "1 update available" badge in the plugin manager.
Can plugins make my data leave OnGravy?
Only if you grant send:webhook. Every outbound call is logged to your audit trail with the URL, payload shape, and timestamp. Admins can revoke send:webhook at any time without uninstalling the plugin.
What languages can I write plugins in?
TypeScript today. The entrypoint is an async function that receives a sandbox context. A WASM runtime is on the roadmap for sandboxed third-party code.
Can a plugin block a voucher from saving?
Not yet — write:vouchers only appends tags. A blocking validator surface (with side_effect:block_save semantics) ships in plugin API v2, mid-2026.