Saltar al contenido principal

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​

TypePurposeDedicated data endpointsWebhook events
paymentProcess payments✅ Capture, order state✅ payment.*, order.*
deliveryDelivery platform integration✅ Order creation, state, menu✅ order.*, menu.*
inventoryStock tracking✅ Ingredients, stock, movements✅ inventory.*
accountingFinancial sync⚠️ Read orders/payments only✅ order.*, payment.*
marketingCampaigns, SMS, email⚠️ Read customers/orders only✅ order.*
analyticsBI and reporting⚠️ Read-only across the API✅ All families
hrScheduling, time tracking❌ No endpoints yet❌ No events yet
reservationTable booking❌ No endpoints yet❌ No events yet
loyaltyRewards and points⚠️ Read customers/orders only✅ order.*, payment.*
All nine are accepted; three are fully served

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" }
BehaviourRule
FrequencyHourly
Timeout5 seconds
HTTP 200 exactlyRecorded as healthy
Slower than 3 secondsRecorded as degraded
Any other status, or a connection failureRecorded as degraded / down
Return 200, not just any 2xx

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.

Design your plugin as a client, not a server

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.

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:

MethodPathPurpose
POST/chargeImmediate payment
POST/refundRefund a transaction
GET/transactions/{id}Transaction status
POST/payment-intentAsync payment (UPI, QR)
POST/payment-intent/{id}/confirmConfirm an intent
POST/payment-intent/{id}/cancelCancel an intent
POST/customersCreate a customer record

SSP authenticates using the auth type you register:

auth_typeHeader sent
api_keyX-API-Key: <your key>
bearerAuthorization: Bearer <your key>
basicAuthorization: Basic <base64>

Requests time out after 30 seconds, and a per-provider max_transaction_amount is enforced before the call.

Async payment intents are not usable yet

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 unsigned

SSP 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.

Two different registrations

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:

  1. Platform notifies you of a new order (their protocol).
  2. You POST /orders with external_order_id set to their order ID — idempotent, so their retries are harmless.
  3. You subscribe to order.status_changed and push kitchen progress back to the platform.
  4. You subscribe to menu.item_updated and menu.item_deleted to keep the platform's menu in sync — the changes object tells you exactly what moved.
  5. You PATCH /menu/{itemId} or POST /menu/bulk-availability when 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:

VerticalWorkable approach today
AccountingSubscribe to order.paid and payment.*; pull order detail via GET /orders/{id}; push into your accounting system
MarketingSubscribe to order.created; read customers with GET /customers; run campaigns in your own system
AnalyticsSubscribe to whichever families you need; warehouse events; enrich via reads
LoyaltySubscribe 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:

CapabilityUnlocks
orders:createPOST /orders
payments:capturePOST /orders/{orderId}/payments

Declare only what you use. Without the capability you get 403 feature_not_enabled.

Also worth setting on your listing:

FieldPurpose
supported_currenciesISO 4217 codes you handle
supported_regionsISO country codes you operate in
supported_eventsWhich webhooks you subscribe to

Next steps​