@nextsparkjs/plugin-social-media-publisher 0.1.0-beta.42 → 0.1.0-beta.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,155 @@
1
+ # OAuth Callback API
2
+
3
+ Handles OAuth redirect from Facebook after user authorization.
4
+
5
+ ## Endpoint
6
+
7
+ ```
8
+ GET /api/v1/plugin/social-media-publisher/social/connect/callback
9
+ ```
10
+
11
+ ## Description
12
+
13
+ This endpoint receives the OAuth redirect from Facebook, exchanges the authorization code for access tokens, encrypts them, and stores connected accounts in the database.
14
+
15
+ ## Query Parameters
16
+
17
+ | Parameter | Type | Description |
18
+ |-----------|------|-------------|
19
+ | `code` | string | Authorization code from Facebook |
20
+ | `state` | string | CSRF token with embedded clientId, platform, mode |
21
+ | `error` | string | (Optional) Error if user denied permission |
22
+ | `error_description` | string | (Optional) Error description |
23
+
24
+ ### State Format
25
+
26
+ The state parameter contains embedded values:
27
+ ```
28
+ {randomState}&platform={platform}&clientId={clientId}&mode={mode}
29
+ ```
30
+
31
+ ## Response
32
+
33
+ This endpoint returns HTML pages that communicate with the parent window via postMessage.
34
+
35
+ ### Success Response
36
+
37
+ Returns HTML page that:
38
+ 1. Displays success message
39
+ 2. Sends postMessage to opener window:
40
+ ```javascript
41
+ {
42
+ type: 'oauth-success',
43
+ platform: 'instagram_business',
44
+ connectedCount: 1
45
+ }
46
+ ```
47
+ 3. Closes popup after 2 seconds
48
+
49
+ ### Preview Mode Response
50
+
51
+ When `mode=preview` in state, returns account data without saving:
52
+ ```javascript
53
+ {
54
+ type: 'oauth-preview',
55
+ platform: 'instagram_business',
56
+ accounts: [
57
+ {
58
+ platform: 'instagram_business',
59
+ platformAccountId: 'ig_123',
60
+ username: '@myaccount',
61
+ accessToken: '...',
62
+ tokenExpiresAt: '2024-03-15T10:30:00Z',
63
+ permissions: ['instagram_basic', 'instagram_content_publish'],
64
+ accountMetadata: {
65
+ followersCount: 5000,
66
+ profilePictureUrl: '...'
67
+ }
68
+ }
69
+ ]
70
+ }
71
+ ```
72
+
73
+ ### Error Response
74
+
75
+ Returns HTML page that:
76
+ 1. Displays error message
77
+ 2. Sends postMessage to opener:
78
+ ```javascript
79
+ {
80
+ type: 'oauth-error',
81
+ error: 'user_cancelled',
82
+ errorDescription: 'You cancelled the authorization process'
83
+ }
84
+ ```
85
+ 3. Closes popup after 3 seconds
86
+
87
+ ## Error Types
88
+
89
+ | Error Type | Description |
90
+ |------------|-------------|
91
+ | `user_cancelled` | User cancelled OAuth flow |
92
+ | `app_not_authorized` | App not authorized by Facebook |
93
+ | `meta_server_error` | Facebook server temporarily unavailable |
94
+ | `missing_client` | Client ID not in state |
95
+ | `missing_code` | Authorization code not provided |
96
+ | `no_instagram_accounts` | No Instagram Business accounts found |
97
+ | `callback_exception` | Server error during processing |
98
+
99
+ ## Account Types
100
+
101
+ ### Instagram Business
102
+
103
+ Fetches Instagram accounts linked to Facebook Pages:
104
+ - Requires Facebook Page with linked Instagram Business Account
105
+ - Returns profile picture, followers count, media count
106
+ - Uses Page access token for Instagram Graph API
107
+
108
+ ### Facebook Page
109
+
110
+ Fetches Facebook Pages the user manages:
111
+ - Returns page name, category, fan count
112
+ - Uses Page access token for publishing
113
+
114
+ ## Token Handling
115
+
116
+ 1. Authorization code exchanged for user access token
117
+ 2. User token exchanged for long-lived Page tokens (60 days)
118
+ 3. Tokens encrypted with AES-256-GCM before storage
119
+ 4. Expiration tracked for auto-refresh on publish
120
+
121
+ ## Database Storage
122
+
123
+ Accounts stored in `clients_social_platforms` table:
124
+ - Linked to client via `parentId`
125
+ - Upsert on `platformAccountId` conflict
126
+ - Audit log entry created for each connection
127
+
128
+ ## Frontend Integration
129
+
130
+ ```typescript
131
+ // Open OAuth popup
132
+ const popup = window.open(
133
+ '/api/v1/plugin/social-media-publisher/social/connect?platform=instagram_business&clientId=xxx',
134
+ 'oauth',
135
+ 'width=600,height=700'
136
+ )
137
+
138
+ // Listen for callback
139
+ window.addEventListener('message', (event) => {
140
+ if (event.origin !== window.location.origin) return
141
+
142
+ if (event.data.type === 'oauth-success') {
143
+ console.log(`Connected ${event.data.connectedCount} accounts`)
144
+ refreshAccountList()
145
+ } else if (event.data.type === 'oauth-error') {
146
+ console.error(event.data.errorDescription)
147
+ }
148
+ })
149
+ ```
150
+
151
+ ## Related APIs
152
+
153
+ - [Connect](/api/v1/plugin/social-media-publisher/social/connect) - Initiate OAuth flow
154
+ - [Publish](/api/v1/plugin/social-media-publisher/social/publish) - Publish content
155
+ - [Disconnect](/api/v1/plugin/social-media-publisher/social/disconnect) - Disconnect account
@@ -0,0 +1,47 @@
1
+ /**
2
+ * API Presets for OAuth Callback
3
+ *
4
+ * OAuth redirect handler - typically not called directly
5
+ */
6
+
7
+ import { defineApiEndpoint } from '@nextsparkjs/core/types/api-presets'
8
+
9
+ export default defineApiEndpoint({
10
+ endpoint: '/api/v1/plugin/social-media-publisher/social/connect/callback',
11
+ summary: 'OAuth callback handler for social media connections (browser redirect)',
12
+ presets: [
13
+ {
14
+ id: 'callback-success',
15
+ title: 'Callback with Code',
16
+ description: 'OAuth callback with authorization code (browser redirect)',
17
+ method: 'GET',
18
+ params: {
19
+ code: '{{authorizationCode}}',
20
+ state: '{{state}}&platform=instagram_business&clientId={{clientId}}'
21
+ },
22
+ tags: ['oauth', 'callback']
23
+ },
24
+ {
25
+ id: 'callback-preview',
26
+ title: 'Callback Preview Mode',
27
+ description: 'OAuth callback in preview mode (returns data without saving)',
28
+ method: 'GET',
29
+ params: {
30
+ code: '{{authorizationCode}}',
31
+ state: '{{state}}&platform=instagram_business&clientId={{clientId}}&mode=preview'
32
+ },
33
+ tags: ['oauth', 'callback', 'preview']
34
+ },
35
+ {
36
+ id: 'callback-error',
37
+ title: 'Callback with Error',
38
+ description: 'OAuth callback when user denies permission',
39
+ method: 'GET',
40
+ params: {
41
+ error: 'access_denied',
42
+ error_description: 'User cancelled the authorization'
43
+ },
44
+ tags: ['oauth', 'callback', 'error']
45
+ }
46
+ ]
47
+ })
@@ -0,0 +1,135 @@
1
+ # Social Media Connect API
2
+
3
+ Initiate OAuth flow and connect Facebook Pages or Instagram Business accounts.
4
+
5
+ ## Endpoints
6
+
7
+ ```
8
+ GET /api/v1/plugin/social-media-publisher/social/connect
9
+ POST /api/v1/plugin/social-media-publisher/social/connect (deprecated)
10
+ ```
11
+
12
+ ## GET - Initiate OAuth Flow
13
+
14
+ Redirects user to Facebook OAuth authorization page to connect their social media accounts.
15
+
16
+ ### Query Parameters
17
+
18
+ | Parameter | Type | Required | Default | Description |
19
+ |-----------|------|----------|---------|-------------|
20
+ | `platform` | string | No | instagram_business | Platform to connect |
21
+ | `clientId` | string | Yes | - | Client ID to associate accounts with |
22
+ | `state` | string | No | - | Random state for CSRF protection |
23
+ | `mode` | string | No | save | "preview" returns data without saving |
24
+
25
+ ### Supported Platforms
26
+
27
+ - `instagram_business` - Instagram Business Account (requires linked Facebook Page)
28
+ - `facebook_page` - Facebook Page
29
+
30
+ ### Example Request
31
+
32
+ ```
33
+ GET /api/v1/plugin/social-media-publisher/social/connect?platform=instagram_business&clientId=client_123&state=abc123
34
+ ```
35
+
36
+ ### Response
37
+
38
+ Redirects to Facebook OAuth authorization URL:
39
+ ```
40
+ https://www.facebook.com/v18.0/dialog/oauth?client_id=...&redirect_uri=...&scope=...&state=...
41
+ ```
42
+
43
+ ### OAuth Scopes Requested
44
+
45
+ **For Instagram Business:**
46
+ - `instagram_basic` - Basic account info
47
+ - `instagram_content_publish` - Publish content
48
+ - `instagram_manage_comments` - Manage comments
49
+ - `pages_show_list` - List Facebook Pages
50
+ - `pages_read_engagement` - Read engagement metrics
51
+
52
+ **For Facebook Pages:**
53
+ - `pages_show_list` - List Facebook Pages
54
+ - `pages_manage_posts` - Publish posts
55
+ - `pages_read_engagement` - Read engagement
56
+
57
+ ## POST - Handle OAuth Callback (Deprecated)
58
+
59
+ Use `/api/v1/plugin/social-media-publisher/social/connect/callback` instead.
60
+
61
+ This endpoint receives the authorization code and exchanges it for access tokens.
62
+
63
+ ### Request Body
64
+
65
+ | Field | Type | Required | Description |
66
+ |-------|------|----------|-------------|
67
+ | `code` | string | Yes | Authorization code from OAuth |
68
+ | `state` | string | No | State for CSRF validation |
69
+ | `platform` | string | Yes | Platform type |
70
+
71
+ ### Success Response (200)
72
+
73
+ ```json
74
+ {
75
+ "success": true,
76
+ "message": "Successfully connected 1 instagram_business account(s)",
77
+ "accounts": [
78
+ {
79
+ "id": "acc_123",
80
+ "platform": "instagram_business",
81
+ "accountName": "@myaccount",
82
+ "permissions": ["instagram_basic", "instagram_content_publish"],
83
+ "metadata": {
84
+ "followersCount": 5000,
85
+ "mediaCount": 150
86
+ },
87
+ "connectedAt": "2024-01-15T10:30:00Z"
88
+ }
89
+ ]
90
+ }
91
+ ```
92
+
93
+ ## Error Responses
94
+
95
+ | Status | Error | Description |
96
+ |--------|-------|-------------|
97
+ | 400 | Missing clientId | clientId parameter required |
98
+ | 400 | Invalid platform | Platform must be facebook_page or instagram_business |
99
+ | 401 | Authentication required | User not logged in |
100
+ | 404 | No Instagram accounts | No Instagram Business accounts found |
101
+ | 500 | OAuth failed | Failed to exchange code for token |
102
+
103
+ ## Setup
104
+
105
+ Configure Facebook OAuth credentials:
106
+
107
+ ```bash
108
+ # plugins/social-media-publisher/.env
109
+ FACEBOOK_CLIENT_ID=your_app_id
110
+ FACEBOOK_CLIENT_SECRET=your_app_secret
111
+ NEXT_PUBLIC_APP_URL=https://your-app.com
112
+ ```
113
+
114
+ ## OAuth Flow
115
+
116
+ 1. Frontend calls GET with clientId and platform
117
+ 2. User redirected to Facebook OAuth
118
+ 3. User authorizes requested permissions
119
+ 4. Facebook redirects to callback endpoint
120
+ 5. Callback exchanges code for tokens
121
+ 6. Tokens encrypted and stored in database
122
+ 7. Popup closes and parent window notified
123
+
124
+ ## Security
125
+
126
+ - All access tokens are encrypted with AES-256-GCM
127
+ - CSRF protection via state parameter
128
+ - Token expiration tracked for auto-refresh
129
+ - Audit logs created for all connections
130
+
131
+ ## Related APIs
132
+
133
+ - [OAuth Callback](/api/v1/plugin/social-media-publisher/social/connect/callback) - OAuth redirect handler
134
+ - [Publish](/api/v1/plugin/social-media-publisher/social/publish) - Publish content
135
+ - [Disconnect](/api/v1/plugin/social-media-publisher/social/disconnect) - Disconnect account
@@ -0,0 +1,48 @@
1
+ /**
2
+ * API Presets for Social Media Connect
3
+ *
4
+ * OAuth connection for Facebook Pages and Instagram Business
5
+ */
6
+
7
+ import { defineApiEndpoint } from '@nextsparkjs/core/types/api-presets'
8
+
9
+ export default defineApiEndpoint({
10
+ endpoint: '/api/v1/plugin/social-media-publisher/social/connect',
11
+ summary: 'Connect Facebook Pages and Instagram Business accounts via OAuth',
12
+ presets: [
13
+ {
14
+ id: 'connect-instagram',
15
+ title: 'Connect Instagram',
16
+ description: 'Initiate OAuth for Instagram Business',
17
+ method: 'GET',
18
+ params: {
19
+ platform: 'instagram_business',
20
+ clientId: '{{clientId}}'
21
+ },
22
+ tags: ['oauth', 'instagram']
23
+ },
24
+ {
25
+ id: 'connect-facebook',
26
+ title: 'Connect Facebook',
27
+ description: 'Initiate OAuth for Facebook Page',
28
+ method: 'GET',
29
+ params: {
30
+ platform: 'facebook_page',
31
+ clientId: '{{clientId}}'
32
+ },
33
+ tags: ['oauth', 'facebook']
34
+ },
35
+ {
36
+ id: 'preview-mode',
37
+ title: 'Preview Mode',
38
+ description: 'Get account data without saving',
39
+ method: 'GET',
40
+ params: {
41
+ platform: '{{platform}}',
42
+ clientId: '{{clientId}}',
43
+ mode: 'preview'
44
+ },
45
+ tags: ['oauth', 'preview']
46
+ }
47
+ ]
48
+ })
@@ -0,0 +1,119 @@
1
+ # Social Media Disconnect API
2
+
3
+ Disconnect (deactivate) a social media account.
4
+
5
+ ## Endpoint
6
+
7
+ ```
8
+ POST /api/v1/plugin/social-media-publisher/social/disconnect
9
+ DELETE /api/v1/plugin/social-media-publisher/social/disconnect/:accountId
10
+ ```
11
+
12
+ ## Authentication
13
+
14
+ Requires dual authentication (session or API key).
15
+
16
+ **Headers:**
17
+ ```
18
+ Authorization: Bearer <session-token>
19
+ # OR
20
+ x-api-key: <api-key>
21
+ x-team-id: <team-id>
22
+ ```
23
+
24
+ ## POST - Disconnect Account
25
+
26
+ Marks a social media account as inactive (soft delete).
27
+
28
+ ### Request Body
29
+
30
+ | Field | Type | Required | Description |
31
+ |-------|------|----------|-------------|
32
+ | `accountId` | string | Yes | Social account UUID |
33
+
34
+ ### Example Request
35
+
36
+ ```json
37
+ {
38
+ "accountId": "123e4567-e89b-12d3-a456-426614174000"
39
+ }
40
+ ```
41
+
42
+ ### Success Response (200)
43
+
44
+ ```json
45
+ {
46
+ "success": true,
47
+ "accountId": "123e4567-e89b-12d3-a456-426614174000",
48
+ "message": "Successfully disconnected @myaccount (instagram_business)"
49
+ }
50
+ ```
51
+
52
+ ## DELETE - Disconnect Account (Alternative)
53
+
54
+ Alternative method using account ID in URL path.
55
+
56
+ ### Example Request
57
+
58
+ ```
59
+ DELETE /api/v1/plugin/social-media-publisher/social/disconnect/123e4567-e89b-12d3-a456-426614174000
60
+ ```
61
+
62
+ ### Success Response (200)
63
+
64
+ Same as POST method.
65
+
66
+ ## Error Responses
67
+
68
+ | Status | Error | Description |
69
+ |--------|-------|-------------|
70
+ | 400 | Validation failed | Invalid request body |
71
+ | 400 | Invalid account ID format | UUID format invalid |
72
+ | 400 | Account already disconnected | Account is already inactive |
73
+ | 401 | Authentication required | Not authenticated |
74
+ | 404 | Account not found | Account doesn't exist or no access |
75
+ | 500 | Failed to disconnect | Server error during operation |
76
+
77
+ ### Example Error
78
+
79
+ ```json
80
+ {
81
+ "error": "Account already disconnected",
82
+ "message": "This account is already inactive."
83
+ }
84
+ ```
85
+
86
+ ## Behavior
87
+
88
+ 1. **Soft Delete**: Account is marked as `isActive = false`, not deleted
89
+ 2. **Tokens Preserved**: Encrypted tokens remain in database for potential reconnection
90
+ 3. **Audit Log**: Disconnect event logged with timestamp and user info
91
+ 4. **Idempotent**: Returns error if already disconnected
92
+
93
+ ## Audit Logging
94
+
95
+ Disconnect events are logged:
96
+
97
+ ```json
98
+ {
99
+ "action": "account_disconnected",
100
+ "details": {
101
+ "platform": "instagram_business",
102
+ "accountName": "@myaccount",
103
+ "success": true,
104
+ "disconnectedAt": "2024-01-15T10:30:00Z"
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## Reconnecting
110
+
111
+ To reconnect a disconnected account:
112
+ 1. Use the [Connect](/api/v1/plugin/social-media-publisher/social/connect) endpoint
113
+ 2. OAuth flow will update the existing record
114
+ 3. Account becomes active again with fresh tokens
115
+
116
+ ## Related APIs
117
+
118
+ - [Connect](/api/v1/plugin/social-media-publisher/social/connect) - Connect accounts
119
+ - [Publish](/api/v1/plugin/social-media-publisher/social/publish) - Publish content
@@ -0,0 +1,34 @@
1
+ /**
2
+ * API Presets for Social Media Disconnect
3
+ *
4
+ * Disconnect (deactivate) social media accounts
5
+ */
6
+
7
+ import { defineApiEndpoint } from '@nextsparkjs/core/types/api-presets'
8
+
9
+ export default defineApiEndpoint({
10
+ endpoint: '/api/v1/plugin/social-media-publisher/social/disconnect',
11
+ summary: 'Disconnect and deactivate social media accounts',
12
+ presets: [
13
+ {
14
+ id: 'disconnect-post',
15
+ title: 'Disconnect Account (POST)',
16
+ description: 'Disconnect account using POST method',
17
+ method: 'POST',
18
+ payload: {
19
+ accountId: '{{accountId}}'
20
+ },
21
+ tags: ['write', 'disconnect']
22
+ },
23
+ {
24
+ id: 'disconnect-delete',
25
+ title: 'Disconnect Account (DELETE)',
26
+ description: 'Disconnect account using DELETE method with path param',
27
+ method: 'DELETE',
28
+ pathParams: {
29
+ accountId: '{{accountId}}'
30
+ },
31
+ tags: ['write', 'disconnect']
32
+ }
33
+ ]
34
+ })
@@ -0,0 +1,169 @@
1
+ # Social Media Publish API
2
+
3
+ Publish content to connected Instagram Business or Facebook Page accounts.
4
+
5
+ ## Endpoint
6
+
7
+ ```
8
+ POST /api/v1/plugin/social-media-publisher/social/publish
9
+ ```
10
+
11
+ ## Authentication
12
+
13
+ Requires dual authentication (session or API key).
14
+
15
+ **Headers:**
16
+ ```
17
+ Authorization: Bearer <session-token>
18
+ # OR
19
+ x-api-key: <api-key>
20
+ x-team-id: <team-id>
21
+ ```
22
+
23
+ ## Request Body
24
+
25
+ | Field | Type | Required | Description |
26
+ |-------|------|----------|-------------|
27
+ | `accountId` | string | Yes | Social platform account ID |
28
+ | `platform` | string | Yes | Platform type (instagram_business, facebook_page) |
29
+ | `imageUrl` | string | No* | Single image URL |
30
+ | `imageUrls` | string[] | No* | Multiple image URLs for carousel (2-10) |
31
+ | `caption` | string | No | Post caption/message |
32
+
33
+ *Instagram requires at least one image. Facebook supports text-only posts.
34
+
35
+ ### Example: Single Image Post
36
+
37
+ ```json
38
+ {
39
+ "accountId": "acc_123",
40
+ "platform": "instagram_business",
41
+ "imageUrl": "https://example.com/photo.jpg",
42
+ "caption": "Check out our new product! #launch"
43
+ }
44
+ ```
45
+
46
+ ### Example: Carousel Post
47
+
48
+ ```json
49
+ {
50
+ "accountId": "acc_123",
51
+ "platform": "instagram_business",
52
+ "imageUrls": [
53
+ "https://example.com/photo1.jpg",
54
+ "https://example.com/photo2.jpg",
55
+ "https://example.com/photo3.jpg"
56
+ ],
57
+ "caption": "Swipe through our collection!"
58
+ }
59
+ ```
60
+
61
+ ### Example: Text-Only Post (Facebook)
62
+
63
+ ```json
64
+ {
65
+ "accountId": "acc_456",
66
+ "platform": "facebook_page",
67
+ "caption": "Exciting news coming soon!"
68
+ }
69
+ ```
70
+
71
+ ## Success Response (200)
72
+
73
+ ```json
74
+ {
75
+ "success": true,
76
+ "platform": "instagram_business",
77
+ "postId": "17895695668004550",
78
+ "postUrl": "https://www.instagram.com/p/ABC123/",
79
+ "message": "Successfully published to instagram_business"
80
+ }
81
+ ```
82
+
83
+ ## Error Responses
84
+
85
+ | Status | Error | Description |
86
+ |--------|-------|-------------|
87
+ | 400 | Validation failed | Invalid request body |
88
+ | 400 | Platform requires image | Instagram requires at least one image |
89
+ | 400 | Invalid image URL | Image URL format invalid |
90
+ | 400 | Invalid caption | Caption exceeds platform limit |
91
+ | 401 | Authentication required | Not authenticated |
92
+ | 403 | Account inactive | Account disconnected, needs reconnection |
93
+ | 403 | Token expired | Token refresh failed, reconnect account |
94
+ | 404 | Account not found | Account doesn't exist or no access |
95
+ | 500 | Publishing failed | API error during publishing |
96
+
97
+ ### Example Error
98
+
99
+ ```json
100
+ {
101
+ "error": "Publishing failed",
102
+ "platform": "instagram_business",
103
+ "details": "Invalid image URL",
104
+ "errorDetails": { ... }
105
+ }
106
+ ```
107
+
108
+ ## Platform Requirements
109
+
110
+ ### Instagram Business
111
+
112
+ - **Image Required**: Yes (single or carousel)
113
+ - **Carousel**: 2-10 images
114
+ - **Caption Limit**: 2,200 characters
115
+ - **Image Formats**: JPEG, PNG
116
+ - **Image Size**: Max 8MB per image
117
+ - **Aspect Ratio**: 4:5 to 1.91:1
118
+
119
+ ### Facebook Page
120
+
121
+ - **Image Required**: No (text-only allowed)
122
+ - **Carousel**: 2-10 images
123
+ - **Caption Limit**: 63,206 characters
124
+ - **Image Formats**: JPEG, PNG, GIF
125
+ - **Image Size**: Max 4MB per image
126
+
127
+ ## Token Auto-Refresh
128
+
129
+ The endpoint automatically handles token refresh:
130
+
131
+ 1. Checks token expiration before publishing
132
+ 2. If expiring within 10 minutes, refreshes token
133
+ 3. Uses Meta's fb_exchange_token endpoint
134
+ 4. Re-encrypts new token in database
135
+ 5. Blocks publish if refresh fails (prevents wasted API calls)
136
+
137
+ ## Audit Logging
138
+
139
+ All publish attempts are logged to `audit_logs` table:
140
+
141
+ ```json
142
+ {
143
+ "action": "post_published",
144
+ "details": {
145
+ "platform": "instagram_business",
146
+ "accountName": "@myaccount",
147
+ "success": true,
148
+ "postId": "17895695668004550",
149
+ "postType": "carousel",
150
+ "imageCount": 3,
151
+ "caption": "...",
152
+ "publishedAt": "2024-01-15T10:30:00Z"
153
+ }
154
+ }
155
+ ```
156
+
157
+ ## Image URL Requirements
158
+
159
+ Image URLs must be:
160
+ - Publicly accessible
161
+ - HTTPS protocol
162
+ - Valid image extension or content-type
163
+ - Not behind authentication
164
+ - Reachable from Meta's servers
165
+
166
+ ## Related APIs
167
+
168
+ - [Connect](/api/v1/plugin/social-media-publisher/social/connect) - Connect accounts
169
+ - [Disconnect](/api/v1/plugin/social-media-publisher/social/disconnect) - Disconnect accounts
@@ -0,0 +1,78 @@
1
+ /**
2
+ * API Presets for Social Media Publish
3
+ *
4
+ * Publish content to Facebook Pages and Instagram Business
5
+ */
6
+
7
+ import { defineApiEndpoint } from '@nextsparkjs/core/types/api-presets'
8
+
9
+ export default defineApiEndpoint({
10
+ endpoint: '/api/v1/plugin/social-media-publisher/social/publish',
11
+ summary: 'Publish photos, carousels, and text posts to social media',
12
+ presets: [
13
+ {
14
+ id: 'instagram-photo',
15
+ title: 'Instagram Photo',
16
+ description: 'Publish single photo to Instagram',
17
+ method: 'POST',
18
+ payload: {
19
+ accountId: '{{accountId}}',
20
+ platform: 'instagram_business',
21
+ imageUrl: '{{imageUrl}}',
22
+ caption: 'Check out our latest post!'
23
+ },
24
+ tags: ['write', 'instagram', 'photo']
25
+ },
26
+ {
27
+ id: 'instagram-carousel',
28
+ title: 'Instagram Carousel',
29
+ description: 'Publish multi-image carousel to Instagram',
30
+ method: 'POST',
31
+ payload: {
32
+ accountId: '{{accountId}}',
33
+ platform: 'instagram_business',
34
+ imageUrls: ['{{imageUrl1}}', '{{imageUrl2}}', '{{imageUrl3}}'],
35
+ caption: 'Swipe through our collection!'
36
+ },
37
+ tags: ['write', 'instagram', 'carousel']
38
+ },
39
+ {
40
+ id: 'facebook-photo',
41
+ title: 'Facebook Photo',
42
+ description: 'Publish photo to Facebook Page',
43
+ method: 'POST',
44
+ payload: {
45
+ accountId: '{{accountId}}',
46
+ platform: 'facebook_page',
47
+ imageUrl: '{{imageUrl}}',
48
+ caption: 'New post on our page!'
49
+ },
50
+ tags: ['write', 'facebook', 'photo']
51
+ },
52
+ {
53
+ id: 'facebook-text',
54
+ title: 'Facebook Text Post',
55
+ description: 'Publish text-only post to Facebook Page',
56
+ method: 'POST',
57
+ payload: {
58
+ accountId: '{{accountId}}',
59
+ platform: 'facebook_page',
60
+ caption: 'Exciting news coming soon!'
61
+ },
62
+ tags: ['write', 'facebook', 'text']
63
+ },
64
+ {
65
+ id: 'facebook-carousel',
66
+ title: 'Facebook Carousel',
67
+ description: 'Publish multi-image carousel to Facebook Page',
68
+ method: 'POST',
69
+ payload: {
70
+ accountId: '{{accountId}}',
71
+ platform: 'facebook_page',
72
+ imageUrls: ['{{imageUrl1}}', '{{imageUrl2}}'],
73
+ caption: 'Check out our photo gallery!'
74
+ },
75
+ tags: ['write', 'facebook', 'carousel']
76
+ }
77
+ ]
78
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/plugin-social-media-publisher",
3
- "version": "0.1.0-beta.42",
3
+ "version": "0.1.0-beta.45",
4
4
  "private": false,
5
5
  "main": "./plugin.config.ts",
6
6
  "requiredPlugins": [],
@@ -10,7 +10,7 @@
10
10
  "react": "^19.0.0",
11
11
  "react-dom": "^19.0.0",
12
12
  "zod": "^4.0.0",
13
- "@nextsparkjs/core": "0.1.0-beta.42"
13
+ "@nextsparkjs/core": "0.1.0-beta.45"
14
14
  },
15
15
  "nextspark": {
16
16
  "type": "plugin",