salla-app-settings
Per-merchant settings for a Salla app. Use when designing a settings schema, registering the form, or reading/writing merchant config. Covers the salla_settings form + optional Validation URL, supported-features declaration (publish-blocker for communication apps), seeding defaults on install, value read/write (POST is a full replace — send ALL keys), reacting to app.settings.updated (activates the app AND is the storage source of truth), and context.settings in App Functions. Admin API → salla-api-core; lifecycle → salla-app-lifecycle.
How do I install this agent skill?
npx skills add https://github.com/sallaapp/salla-partners-agent-kit --skill salla-app-settingsIs this agent skill safe to install?
- Gen Agent Trust Hubpass
This skill is a safe and standard developer guide for managing Salla app settings. It uses official platform tools and follows security best practices for handling sensitive merchant data.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Salla App Settings Flow
Set up per-merchant configuration for a Salla app by performing the actions with the Salla Partners MCP tools. Follow the steps in order — complete each gate before moving on.
Applies to public, private, and communication apps. The merchant settings form (
salla_settings define_form/set_validation_url) is for these app types. Shipping apps have no merchant settings form — they configure shipping viasalla_shipping(zones/settings), a separate concept; the Portal rejectsPOST /settingsfor a shipping app. For a shipping app go to salla-shipping-app.
Critical rule: at runtime, always send ALL keys on every settings POST. Omitting a key sets it to
null— there is no partial update.
Red Flags
| Tempting thought | Why it's wrong |
|---|---|
"Define a salla_settings form for this shipping app." | Shipping apps have no merchant settings form; the Portal rejects POST /settings for them. Configure zones/settings via salla_shipping → salla-shipping-app. |
Tools
| Tool | Action | What it does |
|---|---|---|
salla_settings | define_form | Register the merchant settings form (field objects) |
salla_settings | set_validation_url | Set the server-side Validation URL |
salla_settings | list_features | Read the app's supported features |
salla_settings | set_features | Set supported features |
Prerequisite: the Salla Partners MCP server must be connected. Every action needs the app's
app_id. If a tool returns "Salla session expired", re-run the login flow.
Step 0 — Discover
Ask before starting:
- What merchant inputs does your app need? (API keys, URLs, toggles, numbers?)
- Do you need server-side validation before Salla saves the values?
- When are settings first written? On install, or when the merchant fills the form?
Step 1 — Design the Settings Schema
Salla renders the merchant form from a form-builder schema: every field uses a real
type + format pair from the taxonomy below. Use a real pair (a bare alias like
toggle / text / select is not Portal-safe). Rules:
- Flat only — no nested objects.
idis snake_case (stock_threshold, notstockThreshold) — the installed-app save path is reliable only with snake_case.- Every required field carries a default
value— required for first activation/save. - Arabic-first labels. Most Salla merchants are Arabic — write
label/descriptionin Arabic; setmultilanguage: trueto also provide English.multilanguageapplies to stringtext/textareafields only (the builder gates it viasupportsMultilanguage). public: truemarks a value safe to read client-side. A storefront snippet reads a public setting viasalla.config.get('app.<key>');public: falsevalues stay server-side only. → salla-snippets.- Secrets (API keys, passwords, tokens) use
format: "password", stored encrypted at runtime and read only server-side or viacontext.settings. A password field is inherently non-public — the builder's password control carrieshide: true, which removes the public option, so a secret can never be exposed to the storefront (keeppublic: falseto make the intent explicit). OAuth/merchant access tokens are not settings — handle those via salla-app-auth. - Scopes. Rendering a form or receiving
app.settings.updatedneeds no settings scope; a settings scope is required only to read/write values via the Admin API when activation happens partner-side (not from the merchant dashboard). The Webhooks scope is required if your app listens to any store events.
Use this curated core of type + format pairs:
type | format (core) |
|---|---|
boolean | checkbox (a switch is the same boolean, toggle UI) |
string | text, textarea, password, url, email |
string (value pickers) | color, image, date, time, datetime |
number | integer, float |
items | dropdown-list, radio-list, checkbox-list |
Prefer the simplest type that fits the data. A number (with minimum / maximum /
step) covers what a slider or unit-input would do — don't reach for those. checkbox
covers on/off (a switch is the same boolean). Use textarea for multi-line text.
Advanced formats exist but add complexity — avoid unless genuinely required: richtext
(use textarea unless rich formatting is essential), code, icon, the nested
collection type (repeatable sub-field groups), and static display blocks
(title / description / line). Prefer the core; only use these when the use case truly
needs them.
Common props: id (snake_case), type, format, label, value (default),
required, public, icon, placeholder, labelHTML, multilanguage. Numbers carry
minimum / maximum / step; strings carry minLength / maxLength; items carry
options plus a scalar default value. multilanguage applies to string text /
textarea only. Example checkbox:
{
"id": "hurrify_enabled",
"type": "boolean",
"format": "checkbox",
"label": "تفعيل هيرفاي",
"icon": "sicon-toggle-off",
"value": true,
"required": false,
"public": true
}
Field-object reference → references/form-builder.md
Where the field schema is documented (the OpenAPI block in its docs.salla.dev/<id>.md
page — find it via salla-docs), validate each field object against it — type/format
pairs, required, enums — and fix before define_form, via the read-schema → build →
validate → fix → retry loop in salla-api-core.
Gate: "Every field uses type+format, snake_case ids, Arabic labels, and a default
value on each required field?"
Step 2 — Register the Form
- Call
salla_settingswithaction: "define_form", theapp_id, andsettings(the array of field objects from Step 1). Give each field a plain-stringlabel; setmultilanguage: trueon a stringtext/textareafield whose text should be translated. - Optional Validation URL — validation only, not storage. To reject bad input before
Salla saves it, call
salla_settingswithaction: "set_validation_url",app_id, andvalidation_url. Salla POSTs the proposed values there before saving; respond with field errors (to block) or200 OK(to allow). It is a public endpoint with no signature — validate the values and respond, nothing more. Storage happens via theapp.settings.updatedwebhook (Step 4). Contract →references/form-builder.md.
Manual fallback: Portal → open the app → App Settings form builder.
Gate (save smoke test): "Form registered — install the app on a demo store
(salla_apps action=demo_stores → open a store's install_url, then dashboard_url),
open its settings page, change a value and SAVE, and confirm it persists. The Portal
accepting the schema is NOT proof the installed-app form saves — test the real save."
Validate config usage (this skill owns the contract). The public fields you define
here ARE the keys a storefront snippet can read via salla.config.get('app.<key>'). After
every define_form, confirm: (a) the field schema is valid (the type+format /
snake_case / required-default checks in Step 1), and (b) every salla.config.get('app.<key>')
your snippets read maps to a field defined here with public: true — a missing or private
key reads undefined on the storefront. Settings own the contract; the browser-side check
of those reads lives in salla-snippets.
Step 3 — Declare Supported Features
Optional for most apps — required before publish for communication apps (channel declaration; see salla-communication-app). Manage the flags with the tool:
- Read current:
salla_settings action=list_features,app_id. Note: returns 404 for non-communication apps — this is expected;list_featuresis only meaningful for communication-type apps. - Set them:
salla_settings action=set_features,app_id,features: [...].
Step 4 — Write Defaults on Install (runtime)
There is no MCP tool for writing per-merchant values — that happens at runtime with
the merchant's access_token. When app.store.authorize fires on install, seed any
required defaults so the merchant starts with a working configuration.
app.settings.updatedis the storage source of truth (docs). It fires when the merchant saves the form, activates the app, and carries the full settings indata.settings— persist THAT on every activation/update. It is authoritative (and may arrive before you hold a token), so rely on it rather than a GET. Payload:{ "event": "app.settings.updated", "merchant": 1234509876, "data": { "id": 6789012345, "app_type": "public", "settings": { "door_to_door": true, "pickup_time": "09:00:00", "box_size": ["25x25", "10x10"], "ads_activated": "true" } } }Note booleans may arrive as the string
"true"— coerce defensively. Wiring → salla-app-lifecycle.
Seed defaults on install (handle even if you only re-read the values):
POST https://api.salla.dev/admin/v2/apps/{app_id}/settings
Authorization: Bearer {access_token}
Content-Type: application/json
{
"api_key": "",
"fast_delivery": false,
"contact_no": null
}
Send every key — even empty values. Full install pattern →
references/settings-patterns.md
Step 5 — Read & Update Settings (runtime)
Read:
GET https://api.salla.dev/admin/v2/apps/{app_id}/settings
Authorization: Bearer {access_token}
{
"status": 200,
"success": true,
"data": {
"app_id": "513499943",
"settings": { "api_key": "sk-abc123", "fast_delivery": true }
}
}
Update the form definition (fields, formats, defaults, Validation URL) via the
Partners MCP only — salla_settings action=define_form. That is the one supported way
to change the schema; there is no Portal-side hand-edit you should script around.
Update per-merchant values (runtime) — always send every key (read first, merge your change, write all):
POST https://api.salla.dev/admin/v2/apps/{app_id}/settings
Authorization: Bearer {access_token}
Content-Type: application/json
{ "api_key": "sk-abc123", "fast_delivery": true, "contact_no": 50 }
The POST response body doesn't matter — don't parse or rely on what it echoes back. Treat a 2xx as accepted, then confirm by a follow-up GET (or by the
app.settings.updatedwebhook, which is the storage source of truth).
API spec → references/api-spec.md ·
Safe single-key update → references/settings-patterns.md
Gate: "POST a full settings object and confirm GET returns the updated values."
Step 6 — Access Settings in App Functions
Inside any App Function, settings are on the context object — no API call needed:
export default async function (context: AppContext) {
const apiKey = context.settings?.api_key;
const fastDelivery = context.settings?.fast_delivery;
// always use optional chaining — undefined until merchant configures them
}
App Functions context shape → salla-app-functions
Resources
| Topic | Link |
|---|---|
| Build an App Settings form | references/form-builder.md |
| Salla Admin API reference | https://docs.salla.dev/421117m0.md |
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/sallaapp/salla-partners-agent-kit/salla-app-settings">View salla-app-settings on skillZs</a>