App Manifest Reference
The stripe-app.json manifest file is the central configuration for your Stripe App. It declares your app’s identity, permissions, UI views, security policies, and post-install behavior.
Caution
Status: planned, not built. Tajo has no Stripe App, so nothing in this section can be installed today. The app identifiers, URLs and credentials on this page are illustrative placeholders, not live endpoints.
Full Manifest Example
{ "id": "com.tajo.brevo-integration", "version": "1.2.0", "name": "Tajo for Brevo", "icon": "./assets/icon.png", "distribution_type": "public", "sandbox_install_compatible": true, "stripe_api_access_type": "oauth", "allowed_redirect_uris": [ "https://tajo.io/stripe/callback", "https://tajo.io/stripe/oauth/complete" ], "permissions": [ { "permission": "customer_read", "purpose": "Read customer profiles to sync with Brevo contacts" }, { "permission": "customer_write", "purpose": "Update customer metadata with Brevo sync status" }, { "permission": "charge_read", "purpose": "Access payment history for Brevo event tracking" }, { "permission": "product_read", "purpose": "Sync product catalog to Brevo for personalized campaigns" }, { "permission": "event_read", "purpose": "Read events for Brevo automation triggers" }, { "permission": "invoice_read", "purpose": "Track invoice lifecycle events in Brevo" } ], "ui_extension": { "views": [ { "viewport": "stripe.dashboard.customer.detail", "component": "CustomerDetailView" }, { "viewport": "stripe.dashboard.customer.list", "component": "CustomerListView" }, { "viewport": "stripe.dashboard.home.overview", "component": "OverviewView" }, { "viewport": "stripe.dashboard.drawer.default", "component": "DrawerView" }, { "viewport": "stripe.dashboard.settings", "component": "SettingsView" }, { "viewport": "stripe.dashboard.onboarding", "component": "OnboardingView" } ], "content_security_policy": { "connect-src": [ "https://api.example.com", "https://api.brevo.com" ], "image-src": [ "https://cdn.example.com", "https://assets.brevo.com" ], "purpose": "Connect to Tajo API for data sync and Brevo API for contact management" } }, "post_install_action": { "type": "onboarding" }, "constants": { "API_BASE_URL": "https://api.example.com/v1", "SYNC_INTERVAL_SECONDS": "300" }}Schema Reference
Top-Level Fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique app identifier in reverse domain notation (slug format) |
version | string | Yes | Semantic version string (e.g., "1.2.0") |
name | string | Yes | Display name shown in the marketplace (max 35 characters) |
icon | string | Yes | Relative path to the app icon file (300x300 PNG or SVG) |
distribution_type | string | Yes | "public" for marketplace or "private" for internal use |
sandbox_install_compatible | boolean | No | Whether the app can be installed in sandbox/test mode |
stripe_api_access_type | string | No | API access method: "oauth" or "api_key" |
allowed_redirect_uris | string[] | No | Allowed OAuth redirect URIs for install flow |
permissions | PermissionRequest[] | Yes | Array of permission requests |
ui_extension | UIExtensionManifest | No | UI extension configuration |
post_install_action | PostInstallAction | No | Action to take after app installation |
constants | object | No | Key-value pairs accessible in the app at runtime |
id
The app identifier is a slug-format string, typically in reverse domain notation:
"id": "com.tajo.brevo-integration"- Must be globally unique across all Stripe Apps
- Use lowercase letters, numbers, hyphens, and dots only
- Cannot be changed after the app is created
- Determines the app’s URL on the marketplace
version
Follows semantic versioning:
"version": "1.2.0"- MAJOR: Breaking changes or significant feature additions
- MINOR: New features, backward compatible
- PATCH: Bug fixes and minor improvements
- Must be incremented for each upload
distribution_type
Controls who can install your app:
| Value | Description |
|---|---|
"public" | Available on the Stripe App Marketplace to all users |
"private" | Only installable by your own Stripe account |
stripe_api_access_type
Determines how your app authenticates with the Stripe API:
| Value | Description |
|---|---|
"oauth" | Uses OAuth 2.0 flow for authentication (recommended for public apps) |
"api_key" | Uses restricted API keys (suitable for private apps) |
PermissionRequest
Each permission request declares a specific Stripe API permission your app needs:
{ "permission": "customer_read", "purpose": "Read customer profiles to sync with Brevo contacts"}| Field | Type | Required | Description |
|---|---|---|---|
permission | string | Yes | The permission identifier (see Permissions Reference) |
purpose | string | Yes | Human-readable explanation of why this permission is needed |
Purpose guidelines:
- Write clear, specific explanations that merchants can understand
- Explain what the permission is used for, not just what it grants
- Keep descriptions concise (one sentence)
- Avoid technical jargon
UIExtensionManifest
Configures the UI components of your app:
{ "ui_extension": { "views": [...], "content_security_policy": {...} }}| Field | Type | Required | Description |
|---|---|---|---|
views | ViewManifest[] | Yes | Array of view declarations |
content_security_policy | CSPRequest | No | Content Security Policy for external resources |
ViewManifest
Each view maps a React component to a Stripe Dashboard viewport:
{ "viewport": "stripe.dashboard.customer.detail", "component": "CustomerDetailView"}| Field | Type | Required | Description |
|---|---|---|---|
viewport | string | Yes | The Dashboard location where this view renders (see Viewports Reference) |
component | string | Yes | Name of the React component to render (must match the exported component name) |
A single app can declare multiple views for different viewports:
"views": [ { "viewport": "stripe.dashboard.customer.detail", "component": "CustomerDetailView" }, { "viewport": "stripe.dashboard.payment.detail", "component": "PaymentDetailView" }, { "viewport": "stripe.dashboard.home.overview", "component": "OverviewView" }]CSPRequest
The Content Security Policy controls which external domains your app can connect to:
{ "content_security_policy": { "connect-src": [ "https://api.example.com", "https://api.brevo.com" ], "image-src": [ "https://cdn.example.com" ], "purpose": "Connect to Tajo API for data sync and load images from CDN" }}| Field | Type | Required | Description |
|---|---|---|---|
connect-src | string[] | No | Domains the app can make network requests to |
image-src | string[] | No | Domains the app can load images from |
purpose | string | Yes | Explanation of why these external connections are needed |
Caution
Only include domains that your app actually needs to connect to. Excessive CSP entries may trigger additional review scrutiny.
PostInstallAction
Configures what happens immediately after a user installs your app:
{ "post_install_action": { "type": "onboarding" }}| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | The action type (see below) |
url | string | Conditional | URL for external type actions |
Action Types
| Type | Behavior |
|---|---|
"onboarding" | Opens the app’s onboarding view in the Dashboard |
"settings" | Opens the app’s settings view in the Dashboard |
"external" | Redirects the user to an external URL (requires url field) |
Examples:
// Open onboarding flow{ "post_install_action": { "type": "onboarding" }}
// Open settings page{ "post_install_action": { "type": "settings" }}
// Redirect to external setup{ "post_install_action": { "type": "external", "url": "https://app.tajo.io/stripe/setup" }}See the Post-Install Actions guide for detailed implementation patterns.
Constants
Define static key-value pairs accessible at runtime in your app:
{ "constants": { "API_BASE_URL": "https://api.example.com/v1", "SYNC_INTERVAL_SECONDS": "300", "MAX_BATCH_SIZE": "100" }}- All values must be strings
- Constants are embedded in the app at build time
- Use constants for configuration that varies between environments
- Never store secrets or API keys as constants, use the Secret Store API instead
Access constants in your app code:
import { constants } from '@stripe/ui-extension-sdk/constants';
const apiUrl = constants.API_BASE_URL;Extended Manifest for Development
During local development, additional fields are available:
{ "id": "com.tajo.brevo-integration", "version": "0.1.0", "name": "Tajo for Brevo (Dev)", "icon": "./assets/icon-dev.png", "distribution_type": "private", "sandbox_install_compatible": true, "dev": { "hot_reload": true, "port": 4242 }}The dev section is stripped during production builds and app uploads. Use it for local development convenience settings only.
Validation
Validate your manifest before uploading:
# Validate manifest syntax and schemastripe apps validate
# Check for common issuesstripe apps checkCommon validation errors:
| Error | Cause | Fix |
|---|---|---|
Invalid permission | Unknown permission identifier | Check the Permissions Reference |
Invalid viewport | Unknown viewport identifier | Check the Viewports Reference |
Missing purpose | Permission without purpose field | Add a purpose string to each permission |
Invalid version | Non-semver version string | Use format MAJOR.MINOR.PATCH |
Icon not found | Icon path doesn’t resolve | Verify the icon file exists at the specified path |