Plugin Lifecycle
How a plugin goes from a sandbox scaffold to a listing restaurants can install, and what happens to it afterwards.
Statuses
| Status | Meaning | Production installs authenticate? |
|---|---|---|
scaffold | Auto-created stub so a sandbox has something to attach to | No (sandbox only) |
draft | Yours to edit freely | No |
submitted | Waiting for review | No |
in_review | Reserved. No code path writes it today — a plugin under review stays submitted | No |
changes_requested | Feedback returned — edit and resubmit | No |
approved | Passed review, not yet listed | Yes |
active | Published and live on the marketplace | Yes |
rejected | Declined | No |
suspended | Stopped by a marketplace admin | No |
deprecated | Retired | No |
Only approved and active listings authenticate production traffic, and the
check has no cache. The moment a listing is suspended or deprecated, its
production installations start receiving 403 plugin_listing_unavailable.
Sandbox installations are exempt — you can keep working on a fix.
Creating your plugin
Provisioning a sandbox for a project with no plugin creates a scaffold. When your integration works, promote it with Create Plugin on the project page (requires owner or admin).
Creation returns a new webhook_secret, shown once — update your
environment before testing again.
Required fields
| Field | Notes |
|---|---|
name | Unique slug identifier |
display_name | What restaurants see |
plugin_type | payment, delivery, inventory, accounting, marketing, analytics, hr, reservation, loyalty |
integration_type | rest_api, oauth2, webhook, graphql, soap |
api_endpoint | Your service's base URL |
auth_type | api_key, oauth2, or jwt |
api_key | Credential SSP uses when calling you |
developer_name, developer_email | Contact details shown on the listing |
Optional fields
| Field | Notes |
|---|---|
description | Listing copy |
webhook_endpoint | Must be https — where SSP delivers events |
setup_url | Must be https — your own configuration UI (Setup Handoff) |
documentation_url, icon_url | Listing assets |
supported_events | Which webhooks you subscribe to (catalog) |
supported_features | Capabilities, e.g. orders:create, payments:capture |
supported_currencies, supported_regions | ISO codes |
visibility | private, organization, or public |
pricing_model, price_cents, billing_interval, trial_period_days | See Pricing. Set these after creation — see the note below |
If you set an explicit supported_events list, you must include the
installation.*, subscription.* and trial.* patterns to receive them. A
plugin that provisions tenants headlessly almost certainly wants
installation.*.
createPluginFromProject does not persist the pricing fields, so a plugin
created from a project always lands as free regardless of what you send. Set
pricing with a follow-up update while the plugin is draft, and re-check it
before publishing.
What you can edit, and when
Editable fields depend on status — this is enforced server-side:
| Status | Editable |
|---|---|
draft, active, changes_requested | All fields |
submitted | display_name, description, documentation_url, icon_url only — cosmetic changes mid-review |
| Anything else | Rejected: Cannot update plugin in current status: X |
Review
Submit for review is available from draft or changes_requested only.
Submitting stamps submitted_at and clears any previous round's feedback —
so if review_feedback is empty while you're submitted, there's nothing
outstanding.
Possible outcomes:
| Outcome | What happens |
|---|---|
| Approved | Status becomes approved; you can now publish |
| Changes requested | Returns to you with review_feedback; edit and resubmit |
| Rejected | Status becomes rejected with a reason |
Reviews target a 3–5 business day turnaround.
Passing review
- Your
api_endpointandwebhook_endpointare reachable over public HTTPS. - Signature verification is implemented correctly — a webhook with a bad signature must be rejected.
- The listing describes what the plugin actually does, and
supported_featuresmatches the capabilities you use. - Setup works end to end from a fresh install.
- Errors are handled: your endpoint answers quickly and doesn't 500 on unexpected payloads.
Publishing
Publish requires approved (or an already-active plugin — re-publishing
is idempotent and preserves the original go-live date). Publishing:
- sets status to
activeandis_activeto true, - sets visibility to
publicand lists the plugin on the marketplace, - for paid plugins, creates or syncs the Stripe Product and Price so checkout works.
Unpublish removes the listing from the marketplace.
Pricing
Marketplace v1 supports two models:
pricing_model | Requires | Notes |
|---|---|---|
free | — | No billing |
subscription | price_cents + billing_interval | month or year |
trial_period_days adds a free trial of up to 730 days (0 or null means no
trial). Trials are card up front: Stripe collects the card at install but
doesn't charge until the trial ends.
The published revenue share is 80% to the developer.
The v1 billing pipeline records each invoice in full against the platform; it does not yet compute or disburse a developer split. Confirm payout terms and timing with partnerships@ssppos.com rather than assuming an automated monthly transfer.
Pricing is editable while draft or active. The Stripe Product/Price is
created server-side on publish — you never handle Stripe credentials.
What a restaurant experiences
| Plugin | Install flow |
|---|---|
| Free | Installs immediately, status active |
| Paid | Install creates a pending_payment hold, and the operator is sent to Stripe Checkout. The installation activates when payment completes |
| Paid with a trial | The trial starts on install; one trial per organization per plugin, and uninstalling doesn't reset it |
Your plugin is told about all of this by webhook: installation.created,
trial.started, trial.ending, subscription.activated, and
installation.removed. Use them to provision and tear down tenants without any
manual step. See Webhooks.
A paid install sits in pending_payment until checkout completes. Wait for
subscription.activated (or trial.started) before enabling paid features.
Changelogs
Publish release notes against your listing:
| Field | Rules |
|---|---|
version | Required, max 20 characters |
changes | Required — the release notes |
change_type | major, minor, patch, or hotfix |
released_at | Optional timestamp |
Entries can be updated or deleted by the plugin owner.
Reviews and ratings
Restaurants that have installed your plugin can leave a 1–5 star rating with optional text. As the owner you can respond to any review, and your listing carries a rating average, rating count, and review count.
The response is stored, but no public API field exposes it yet, so it does not appear on the marketplace listing.
Certification
Certified plugins get a badge and better marketplace placement. Certification is
granted by SSP at basic, advanced, or enterprise level.
Cost: $1,000 — contact partnerships@ssppos.com.
Monitoring your listing
The portal exposes per-plugin statistics (installs, request counts, health) and
per-installation health status. SSP periodically health-checks your
api_endpoint and records the result on each installation.
Suspension and deprecation
A marketplace admin can suspend a listing — status becomes suspended,
is_active becomes false, and production installations lose runtime access
immediately. Reinstating restores the pre-suspension status.
Deprecating retires a plugin. As with suspension, production installations stop authenticating.
In both cases your sandbox keeps working, so you can develop and test a remedy.
Next steps
- Setup Handoff — hosting your own configuration UI
- Webhooks — the installation, trial and subscription events
- Security — what reviewers look for