Plugin Types
plugin_type is a required field on every listing. It drives marketplace
categorisation and tells restaurants what your plugin is for.
The nine types
| Type | Purpose | Dedicated data endpoints | Webhook events |
|---|---|---|---|
payment | Process payments | ✅ Capture, order state | ✅ payment.*, order.* |
delivery | Delivery platform integration | ✅ Order creation, state, menu | ✅ order.*, menu.* |
inventory | Stock tracking | ✅ Ingredients, stock, movements | ✅ inventory.* |
accounting | Financial sync | ⚠️ Read orders/payments only | ✅ order.*, payment.* |
marketing | Campaigns, SMS, email | ⚠️ Read customers/orders only | ✅ order.* |
analytics | BI and reporting | ⚠️ Read-only across the API | ✅ All families |
hr | Scheduling, time tracking | ❌ No endpoints yet | ❌ No events yet |
reservation | Table booking | ❌ No endpoints yet | ❌ No events yet |
loyalty | Rewards and points | ⚠️ Read customers/orders only | ✅ order.*, payment.* |
Every value registers and installs. Three verticals — payment, delivery, inventory — have dedicated write endpoints. The ones marked ⚠️ are genuinely buildable today using the read surface plus webhooks; the ❌ types have no data to work with yet.
Building in one of those areas? Email developers@ssppos.com — early designs are open to feedback.
What SSP calls on your service
This is the part most often misunderstood. For a marketplace plugin, SSP makes exactly two kinds of call to you:
1. GET {api_endpoint}/health
A periodic health check. No authentication is sent.
{ "status": "ok", "version": "1.2.0" }
| Behaviour | Rule |
|---|---|
| Frequency | Hourly |
| Timeout | 5 seconds |
| HTTP 200 exactly | Recorded as healthy |
| Slower than 3 seconds | Recorded as degraded |
| Any other status, or a connection failure | Recorded as degraded / down |
The check tests for 200 specifically. A /health answering 204 No Content
is recorded as degraded and shown that way on your public listing.
Health status is visible to restaurants on your listing, so keep this endpoint cheap — don't touch your database or a third-party API in it.
2. POST {webhook_endpoint}
Signed event delivery. See Webhooks.
That's the whole inbound surface. Everything else — reading orders, writing
payments, updating menus — is your plugin calling SSP, authenticated with your
pik_ key. You do not need to implement /orders, /charge, /menu/sync, or
anything else on your side unless you want to.
Apart from /health, a webhook receiver, and optionally a
setup page, your service defines its own shape. Build the
API your product needs; SSP won't call it.
Payment plugins
Payment integrations come in two distinct flavours, and choosing the right one matters.
Flavour A — marketplace payment plugin (recommended)
Your plugin collects payment through your own provider, then records the capture with SSP:
You need the payments:capture capability. Your plugin owns the payment UX; SSP
owns the ledger. Details:
Payment Gateways.
Flavour B — external gateway provider
SSP calls your service to move money, using it as a drop-in gateway alongside its built-in ones. This is a separate registration from the plugin marketplace, and it requires you to implement a fixed contract:
| Method | Path | Purpose |
|---|---|---|
POST | /charge | Immediate payment |
POST | /refund | Refund a transaction |
GET | /transactions/{id} | Transaction status |
POST | /payment-intent | Async payment (UPI, QR) |
POST | /payment-intent/{id}/confirm | Confirm an intent |
POST | /payment-intent/{id}/cancel | Cancel an intent |
POST | /customers | Create a customer record |
SSP authenticates using the auth type you register:
auth_type | Header sent |
|---|---|
api_key | X-API-Key: <your key> |
bearer | Authorization: Bearer <your key> |
basic | Authorization: Basic <base64> |
Requests time out after 30 seconds, and a per-provider
max_transaction_amount is enforced before the call.
POST /payment-intent is documented to receive a callback_url for posting
the outcome, but the route that URL points at is not registered in the
backend, so generating it throws before the request leaves SSP. Treat the
/payment-intent half of this contract as not yet functional and build against
/charge and /refund only. Raise it with partnerships@ssppos.com if you need
async flows.
GET /transactions/{id} arrives unsignedSSP sends only Content-Type and your configured auth header on this path —
there is no X-SSP-Signature on outbound gateway calls. If you implement a
mandatory signature check on it, every status poll will be rejected.
Flavour B is not created by publishing a marketplace plugin. Contact partnerships@ssppos.com if you want SSP to route payments through your gateway directly.
Delivery plugins
Delivery integrations originate orders in SSP from an external platform.
Capability required: orders:create
Typical shape:
- Platform notifies you of a new order (their protocol).
- You
POST /orderswithexternal_order_idset to their order ID — idempotent, so their retries are harmless. - You subscribe to
order.status_changedand push kitchen progress back to the platform. - You subscribe to
menu.item_updatedandmenu.item_deletedto keep the platform's menu in sync — thechangesobject tells you exactly what moved. - You
PATCH /menu/{itemId}orPOST /menu/bulk-availabilitywhen the platform reports items as unavailable.
DINE_IN is not creatable through the API — table management belongs to the POS
register. Use DELIVERY, TAKEAWAY, PICKUP, or TAKEOUT.
Details: Delivery Platforms.
Inventory plugins
Inventory integrations keep an external stock system and SSP in step.
Read: ingredients with per-location stock, reorder points, par levels, and
the last 20 movements. ?low_stock=true gives you a one-call reorder report.
Write: signed movements against the append-only ledger — receive,
adjust, consume, waste, transfer, count — plus allow-listed metadata
updates (name, sku, unit, cost_per_unit, supplier, allergens).
React: inventory.stock_updated on every movement,
inventory.low_stock and inventory.low_stock_resolved on threshold
crossings.
Stock quantities are only movable through the ledger, so history is always complete and auditable.
Details: Plugin Data API — Inventory.
Building in a partially-served vertical
accounting, marketing, analytics, and loyalty have no dedicated write
endpoints, but the read surface plus webhooks is often enough:
| Vertical | Workable approach today |
|---|---|
| Accounting | Subscribe to order.paid and payment.*; pull order detail via GET /orders/{id}; push into your accounting system |
| Marketing | Subscribe to order.created; read customers with GET /customers; run campaigns in your own system |
| Analytics | Subscribe to whichever families you need; warehouse events; enrich via reads |
| Loyalty | Subscribe to order.paid; identify the customer via customer_id; award points in your own store |
The gap is writing back into SSP — there is no endpoint to attach loyalty points or a marketing consent flag to an SSP customer today. Keep that state in your own system and surface it through your own UI (setup handoff gives you a place to put it).
Declaring capabilities
supported_features is the array that unlocks gated write endpoints:
| Capability | Unlocks |
|---|---|
orders:create | POST /orders |
payments:capture | POST /orders/{orderId}/payments |
Declare only what you use. Without the capability you get
403 feature_not_enabled.
Also worth setting on your listing:
| Field | Purpose |
|---|---|
supported_currencies | ISO 4217 codes you handle |
supported_regions | ISO country codes you operate in |
supported_events | Which webhooks you subscribe to |
Next steps
- Plugin Data API — the endpoints behind each vertical
- Webhooks — the event catalog
- Plugin Lifecycle — registering and publishing