skilly. Buy ad slot
All skills
Backend · Communication · Security / AGENT SKILL

sender-profile-architect

sentdm/sent-plugin
2.9K installs 47 GitHub stars
0

Designs Sent Sender Profiles for tenant isolation, multiple brands, channel sharing, billing, and scoped access.
Designs Sent Sender Profile architecture for multi-tenant, multi-brand, and multi-channel systems. Use for API-key scoping, x-profile-id, isolation, inheritance, sharing, billing, WABA, 10DLC campaigns, webhooks, or tenant offboarding.

BEFORE YOU INSTALL

Understand the trade-offs.

SECURITY REVIEW

Not yet assessed

Review the original instructions and requested permissions before installing.

No security review is available for this catalog entry yet.

SKILL QUALITY

Not yet assessed

How clearly the skill guides your agent, how complete its workflow is, and how you can check the outcome.

No quality assessment is available for this catalog entry yet.

The full skill.

Original instructions from the publisher’s SKILL.md

# Sender Profile Architect

A Sender Profile is the operational boundary for tenant identity, channel configuration, inherited resources, billing, and credentials. Use this skill before provisioning when a poor boundary would mix brands, compliance posture, rate-limit impact, or webhook ownership.

## Recommended tenancy model

When tenants require isolation, recommend one Sent organization with one Sender Profile per tenant. A shared profile is appropriate only when the tenants genuinely share one brand, sender resources, compliance posture, billing/rate-limit expectations, and operational blast radius.

Do not recommend pooled-by-default architecture. Make the isolation decision explicit using [references/multi-tenancy-patterns.md](references/multi-tenancy-patterns.md).

## Authentication patterns

Sent v3 supports both:

| Pattern | Headers | Blast radius |
| --- | --- | --- |
| Profile-specific API key | `x-api-key` | Profile-scoped credentials and rate-limit context. Do not add `x-profile-id`. |
| Organization API key acting for a child | `x-api-key` plus `x-profile-id: <profile UUID>` | Organization credential can reach permitted child profiles; rate limits remain in the organization pool. |

Only organization keys may send `x-profile-id`. A profile key that sends it receives `403`. A profile outside the organization returns `404`. `X-Profile-Id` can be echoed in scoped responses.

`x-sender-id` is legacy v1/v2 terminology only. Do not use it for v3 authentication or routing.

Choose profile keys when tenant-level credential isolation and revocation are primary. Choose organization-key scoping for centrally controlled integrations that can protect a broader credential and deliberately accept a shared organization rate-limit pool.

## Profile creation model

Create with `POST /v3/profiles`. `name` is required. Current optional areas include:

- identity: `icon`, `description`, `short_name`;
- sharing: `allow_contact_sharing`, `allow_template_sharing`;
- inheritance: `inherit_contacts`, `inherit_templates`, `inherit_tcr_brand`, `inherit_tcr_campaign`;
- billing: `billing_model`, `billing_contact`, and ephemeral `payment_details`;
- dedicated WABA credentials: `whatsapp_business_account` with `waba_id`, optional `phone_number_id`, and `access_token`;
- a dedicated brand: `brand.contact`, `brand.business`, and `brand.compliance`.

Do not add a separate brand endpoint. A dedicated brand is created with the profile; campaigns are managed under `/v3/profiles/{profileId}/campaigns`.

### Inheritance rules

- `inherit_tcr_brand: true` means the profile uses the organization's brand and cannot submit its own `brand` object.
- `inherit_tcr_campaign: true` makes inherited campaigns read-only for that profile.
- An inherited brand with `inherit_tcr_campaign: false` is a supported dedicated-campaign pattern.
- Sharing flags expose a profile's contacts/templates; inheritance flags consume organization resources. Treat those directions separately.

### Billing and number references

`billing_model` currently supports `profile`, `organization`, and `profile_and_organization`. A profile or fallback billing model requires `billing_contact` when none exists. Card fields are forwarded to the payment processor and must not be logged or persisted.

Profile update can manage `sending_phone_number_profile_id`, `sending_whatsapp_number_profile_id`, `sending_phone_number`, `whatsapp_phone_number`, and `allow_number_change_during_onboarding`. Model reference IDs and direct numbers separately, and prevent cycles when one profile references another.

## WABA choices

There are three distinct paths:

1. Organization Embedded Signup in the dashboard.
2. Child profile inheritance by omitting `whatsapp_business_account` after the organization has a WABA.
3. Dedicated profile WABA using `waba_id` and `access_token`; `phone_number_id` is optional.

There is no public endpoint that starts organization Embedded Signup. Direct credentials on `POST /v3/profiles` are not an “Embedded Signup endpoint.” Use `waba-embedded-signup` for the operational flow.

## 10DLC and campaigns

Use a profile `brand` object for a dedicated brand. Manage campaigns at:

- `GET|POST /v3/profiles/{profileId}/campaigns`
- `PUT|DELETE /v3/profiles/{profileId}/campaigns/{campaignId}`

Use `sms-10dlc-registration` for the payload and policy layer.

## Completion and status handling

Complete a profile with `POST /v3/profiles/{profileId}/complete` and a required `webHookUrl`:

```json
{
  "webHookUrl": "https://example.com/webhooks/profile-complete",
  "sandbox": true
}
```

Status is surface-specific:

- Create response currently demonstrates lowercase `incomplete`.
- Completion `202` means processing started and does not contain a final status.
- Completion `200` currently demonstrates lowercase `completed` for an already-complete profile.
- Completion callbacks can report `COMPLETED`, `SUBMITTED`, or `failed`.
- REST guides and OpenAPI publish different profile status sets.

Do not assert a closed REST enum. Preserve unknown strings and record the endpoint/callback surface that produced them.

## Webhook attribution

Sent events do not contain your application tenant ID. Before sending, persist the returned `message_id` with the tenant and profile. Route outbound status events through that mapping. For inbound messages, map the receiving number/profile resource to the tenant.

```text
message_id -> tenant_id, profile_id, logical_send_id, channel
receiving_number -> tenant_id, profile_id
```

Do not infer tenant ownership from `account_id` alone. Multiple tenant profiles can belong to one organization.

## Design checklist

- [ ] Tenant/brand isolation decision is explicit.
- [ ] Credential pattern and rate-limit/blast radius are documented.
- [ ] Sharing and inheritance directions are intentional.
- [ ] Billing ownership is named.
- [ ] Number references cannot form cycles.
- [ ] WABA path is organization signup, inheritance, or dedicated credentials—not an invented hybrid.
- [ ] Dedicated brand/campaign paths are profile-based.
- [ ] `message_id` and inbound-number mappings support webhook attribution.
- [ ] Unknown profile statuses are tolerated.
- [ ] Tenant offboarding revokes credentials, disables sends, detaches resources safely, and retains audit evidence.

See [references/sender-profile-data-model.md](references/sender-profile-data-model.md) and [references/profile-boundary-examples.md](references/profile-boundary-examples.md) for implementation patterns.