sallaapp/salla-partners-agent-kit

salla-communication-app

Build a Salla Communication App that delivers SMS, WhatsApp, or email on the merchant's behalf. Use when building channel apps, OTP/notification delivery, or the communication.*.send events. Salla deltas: no sub_category_id, zero default webhooks, channels MUST be declared via supported-features before publish (else 403), and each send event is an App Function trigger — prefer App Functions. App creation → salla-app-builder; credentials → salla-app-settings; handler code → salla-app-functions; …

First seen Jun 30, 2026

Installation

$ npx skills add sallaapp/salla-partners-agent-kit --skill salla-communication-app

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from sallaapp/salla-partners-agent-kit · top by installs.

npx skills add sallaapp/salla-partners-agent-kit

Browse all from sallaapp/salla-partners-agent-kit

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 2
License LICENSE
Default branch master
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 12,184 B
  • docs SUMMARY.md 569 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 58 installs

SKILL.md

Salla Communication App

A Communication App is an App Function that takes over message delivery for SMS, Email, or WhatsApp. When a store event fires (order status change, OTP request, abandoned cart, …), Salla calls your function with the composed message. Your function reads provider credentials from context.settings, calls the provider (Twilio / SendGrid / 360dialog / Unifonic / any), and returns the result via the Resp utility. You own routing and delivery; Salla owns the trigger. (Overview)

Prerequisite: a working grasp of App Functions ([salla-app-functions](../salla-app-functions/SKILL.md)) — the runtime, Resp, and the sandbox limits are not duplicated here. (Get Started)

Step 1 — Create the app

Follow [salla-app-builder](../salla-app-builder/SKILL.md) with type: "communication". Selecting the Communication App category is what unlocks the Supported Features section (Step 2) — without it the channel options never appear. (Channels Config) Deltas from a General App:

  • No subcategoryid — communication apps don't use one (only app and shipping types

do). They still need a maincategoryid at publish — that's the shared "App Theme"/"App Impact" list (sallareference action=categoriesmaincategories), not a communication-specific tree.

  • 0 default webhooks — nothing is subscribed for you (shipping apps get default shipment events; you get none).
  • is_embedded defaults to true.

Gate: "App created with type: "communication", and the Supported Features section is now visible?"

Step 2 — Declare supported channels (publish-blocker)

Supported Features declare which channels your app handles. Once a merchant installs your app and sets it as the active handler for a channel, Salla stops using its default delivery layer and routes every matching message to your App Function — your app takes full ownership of that message type. Before publishing you MUST declare at least one channel: (Channels Config)

  • MCP: sallasettings action=setfeatures with any of sms_local,

smsinternational, emailall, whatsapp.

  • Read currently-set features: sallasettings action=listfeatures. (Returns only the features already configured, not the full types schema. Valid channel values — smslocal, smsinternational, email_all, whatsapp — come from the tool schema, not the API response. The tool wraps the supported-features endpoints — never call them directly.)
Feature set_features value Event What you handle
Local SMS sms_local communication.sms.send SMS to KSA numbers (+966…)
International SMS sms_international communication.sms.send SMS outside KSA
Email email_all communication.email.send All email
WhatsApp whatsapp communication.whatsapp.send All WhatsApp

Publishing without features fails with 403 communicationappnothavefeatures (slug and channel values are surfaced by the salla_settings tool schema — verify current values via the Partners MCP or the Portal if they ever change).

SMS apps need a CITC certification to publish. A communication app that supports SMS
(smslocal / smsinternational) must upload its CITC certification on the account
verification form (https://portal.salla.partners/account) — a Saudi regulatory requirement.
App details expose requirescitc (apppublish action=get / salla_apps action=get):
when true, the certificate is still needed. The partner verifies the account and uploads it
before the publish request; until then submission is blocked. Publication flow →
salla-publication-consistency.

Gate: "At least one channel declared via sallasettings action=setfeatures — and, for an SMS app, requires_citc reads false?"

Step 3 — Set up the provider

Pick a delivery provider and obtain its credentials before writing code. The doc walks Twilio as the worked case (Provider/Twilio): create an account, claim a phone number, and save the Account SID, Auth Token, and sender number (for WhatsApp, join the Twilio sandbox from your own verified number — in testing, messages only reach verified sandbox numbers). The same shape applies to any provider (SendGrid API key, Meta Graph token + phone-number id, etc.) — only the field names differ.

You enter these as App Settings so each merchant supplies their own; never hardcode them. The settings FORM definition (field schema, public:false for secrets) lives in [salla-app-settings](../salla-app-settings/SKILL.md); at runtime they arrive as context.settings.

Step 4 — Build the App Function

The three events are App Function triggers — per the hookable rule, implement them as App Functions ([salla-app-functions](../salla-app-functions/SKILL.md)) rather than webhooks: no server, and the merchant's provider credentials arrive in context.settings.

In the Portal function builder, click Select Action and pick the channel event you want to handle. One function per channel, or a single master function that branches on context.payload.event. The handler reads the payload + settings, calls the provider, and returns Resp.success() / Resp.error():

export default async (context: CommunicationEvent): Promise<Resp> => {
  const { payload, settings } = context;
  const { notifiable, content } = payload.data;

  if (!settings.sms_api_key) {
    return Resp.error()
      .setMessage("Missing provider credentials.")
      .setStatus(422);
  }
  try {
    const res = await fetch(`${settings.sms_base_url}/send`, {
      method: "POST",
      signal: AbortSignal.timeout(10_000),
      headers: {
        Authorization: `Bearer ${settings.sms_api_key}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ to: notifiable[0], text: content }),
    });
    return res.ok ? Resp.success() : Resp.error().setStatus(res.status);
  } catch (err: any) {
    return Resp.error().setMessage("Delivery failed.").setStatus(500);
  }
};

Every event delivers the same payload in context.payload.data (notifiable, type, content, entity, meta) plus credentials in context.settings. Local SMS and International SMS share the single communication.sms.send event — route by the notifiable[0] number prefix if you need provider-specific handling. Full event list, typed shape, real examples, and handling patterns: [references/communication-events.md](references/communication-events.md).

Only fall back to webhook subscriptions for these events if delivery must run on your own infrastructure ([salla-webhooks](../salla-webhooks/SKILL.md)).

This app sends real customer messages, so keep content, notifiable, and settings credentials out of logs and validate the provider endpoint before calling it — full secret & PII rules in [references/communication-events.md](references/communication-events.md).

Gate: "Each channel handled by an App Function that reads credentials from context.settings and returns Resp.success()/Resp.error() — no hardcoded keys, no custom server?"

Step 5 — Test

Two stages (Test & Go Live):

  1. Preview panel — in the function editor, Select Store (demo store), enter a

preview parameter (usually a customer id whose phone is your verified test number), then Save and Preview. The panel shows execution status, returned data, run time, console.log() output, and error traces. If context.settings is empty, you haven't filled the App Settings form on the demo store. Preview via [salla-app-functions-test](../salla-app-functions-test/SKILL.md).

  1. End-to-end from the dashboard — install on the demo store, set your app as the

active handler under Apps → Settings → Customize, then trigger a real message (e.g. change an order status to fire communication.*.send) and confirm it arrives via your provider. Full demo-store run: [salla-live-testing](../salla-live-testing/SKILL.md).

Gate: "A real communication.*.send event from the demo store delivered end-to-end through your provider?"

Step 6 — Go live

Standard publish flow via [salla-app-builder](../salla-app-builder/SKILL.md). Gate: Step 2 features are set and send handlers pass both test stages above. Edits stay in a sandbox until you publish; merchants who already installed the app receive the updated function automatically once published — no reinstall. (Test & Go Live)

Red Flags

Tempting thought Why it's wrong
"I'll declare the supported features later, after the code works." Publishing with zero declared channels fails 403 communicationappnothavefeatures — declare ≥1 via sallasettings action=setfeatures BEFORE publish (Step 2).
"The SMS app is ready to submit once delivery works." An SMS app (smslocal/smsinternational) stays blocked until the CITC certificate is uploaded on the account verification form — confirm requires_citc is false first (Step 2).
"I'll stand up a webhook server to receive the send events." The send events are App Function triggers — implement them as App Functions (no server; credentials arrive in context.settings). Fall back to webhooks only if delivery must run on your own infra (Step 4).
"I'll store the merchant's provider keys in my own database." Provider credentials are per-merchant App Settings read from context.settings at runtime — never hardcode them or store them outside salla_settings (Step 3).

Resources