faceless-cli 1.1.17 → 1.1.19
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.
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/generated/operations.json +479 -1
- package/src/index.mjs +80 -0
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ Key precedence: `--api-key` flag, then `FACELESS_API_KEY`, then the config file.
|
|
|
37
37
|
| `faceless logout` | Remove the saved API key |
|
|
38
38
|
| `faceless whoami` | Identify the caller (team, plan, scopes) |
|
|
39
39
|
| `faceless credits` | Credit balance and history |
|
|
40
|
+
| `faceless buy-credits` | Buy a credit pack with an agent payment token (`--pack`, `--token`) |
|
|
40
41
|
| `faceless videos create` | Create a faceless video from a script (charges credits) |
|
|
41
42
|
| `faceless videos captions` | Caption an existing video or audio URL |
|
|
42
43
|
| `faceless videos list` | List the team's videos |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generatedFrom": "src/backend/api/v1/spec/registry.mjs",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.19",
|
|
4
4
|
"baseUrl": "https://faceless.so/api/v1",
|
|
5
5
|
"operations": [
|
|
6
6
|
{
|
|
@@ -105,6 +105,67 @@
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
|
+
{
|
|
109
|
+
"operationId": "buyCredits",
|
|
110
|
+
"method": "post",
|
|
111
|
+
"path": "/credits",
|
|
112
|
+
"resource": "credits",
|
|
113
|
+
"summary": "Buy a credit pack with an agent payment token",
|
|
114
|
+
"description": "Buys a credit pack and adds the credits to the team immediately, paid with a Stripe Shared Payment Token (spt_...) that the customer approved in their Link agent wallet. Packs: pack_10 ($10, 100 credits), pack_25 ($25, 275), pack_50 ($50, 600); active subscribers get more credits per pack at their plan rate. Request the token for the Faceless.so Stripe profile (profile_61UDMKC11wsLfeXaMA6UDMKCL0SQKAF3aHKCFz33IPL6) with a USD max_amount of at least the pack price. Tokens are single use: retrying with the same token never charges twice. A declined, expired or already used token returns 402 payment_failed.",
|
|
115
|
+
"scopes": [
|
|
116
|
+
"credits:write"
|
|
117
|
+
],
|
|
118
|
+
"status": 201,
|
|
119
|
+
"idempotent": true,
|
|
120
|
+
"terminalStates": null,
|
|
121
|
+
"creditCost": "none (adds credits; charges the payment token the pack price in USD)",
|
|
122
|
+
"cli": {
|
|
123
|
+
"command": "buy-credits"
|
|
124
|
+
},
|
|
125
|
+
"mcp": {
|
|
126
|
+
"name": "faceless_buy_credits",
|
|
127
|
+
"enabled": false
|
|
128
|
+
},
|
|
129
|
+
"querySchema": null,
|
|
130
|
+
"requestSchema": {
|
|
131
|
+
"type": "object",
|
|
132
|
+
"properties": {
|
|
133
|
+
"packId": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"enum": [
|
|
136
|
+
"pack_10",
|
|
137
|
+
"pack_25",
|
|
138
|
+
"pack_50"
|
|
139
|
+
],
|
|
140
|
+
"description": "Credit pack to buy: pack_10 ($10), pack_25 ($25) or pack_50 ($50)"
|
|
141
|
+
},
|
|
142
|
+
"paymentToken": {
|
|
143
|
+
"type": "string",
|
|
144
|
+
"pattern": "^spt_[A-Za-z0-9_]+$",
|
|
145
|
+
"description": "Stripe Shared Payment Token granted to Faceless.so by the customer's agent wallet"
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"required": [
|
|
149
|
+
"packId",
|
|
150
|
+
"paymentToken"
|
|
151
|
+
],
|
|
152
|
+
"additionalProperties": false
|
|
153
|
+
},
|
|
154
|
+
"requestExample": {
|
|
155
|
+
"packId": "pack_10",
|
|
156
|
+
"paymentToken": "spt_1Rx2abc"
|
|
157
|
+
},
|
|
158
|
+
"responseExample": {
|
|
159
|
+
"success": true,
|
|
160
|
+
"data": {
|
|
161
|
+
"packId": "pack_10",
|
|
162
|
+
"amountUsd": 10,
|
|
163
|
+
"creditsAdded": 100,
|
|
164
|
+
"balance": 440,
|
|
165
|
+
"paymentIntentId": "pi_3Rx2abc"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
108
169
|
{
|
|
109
170
|
"operationId": "createVideo",
|
|
110
171
|
"method": "post",
|
|
@@ -1926,6 +1987,423 @@
|
|
|
1926
1987
|
"timeseriesReady": true
|
|
1927
1988
|
}
|
|
1928
1989
|
}
|
|
1990
|
+
},
|
|
1991
|
+
{
|
|
1992
|
+
"operationId": "searchAds",
|
|
1993
|
+
"method": "get",
|
|
1994
|
+
"path": "/ads/search",
|
|
1995
|
+
"resource": "ads",
|
|
1996
|
+
"summary": "Search Meta ads shown in the EU and UK",
|
|
1997
|
+
"description": "Searches the official Meta Ad Library by keywords in the ad text or by one advertiser's exact Facebook Page ID. Meta only returns commercial ads delivered in the EU and UK, so the country is one of those or EU_UK for all of them. Returns up to 25 ads (copy variants, delivery dates, platforms, a public Meta link), a resultToken to save or brief any of them within 15 minutes, and an opaque nextCursor. Free; each team has a daily search allowance and cached repeats do not count against it. No media files are returned.",
|
|
1998
|
+
"scopes": [
|
|
1999
|
+
"ads:read"
|
|
2000
|
+
],
|
|
2001
|
+
"status": 200,
|
|
2002
|
+
"idempotent": false,
|
|
2003
|
+
"terminalStates": null,
|
|
2004
|
+
"creditCost": "none",
|
|
2005
|
+
"cli": {
|
|
2006
|
+
"command": "ads search"
|
|
2007
|
+
},
|
|
2008
|
+
"mcp": {
|
|
2009
|
+
"name": "faceless_search_ads",
|
|
2010
|
+
"enabled": false
|
|
2011
|
+
},
|
|
2012
|
+
"querySchema": {
|
|
2013
|
+
"type": "object",
|
|
2014
|
+
"properties": {
|
|
2015
|
+
"q": {
|
|
2016
|
+
"type": "string",
|
|
2017
|
+
"minLength": 1,
|
|
2018
|
+
"maxLength": 100,
|
|
2019
|
+
"description": "Words in the ad text. Send q or pageId, not both."
|
|
2020
|
+
},
|
|
2021
|
+
"pageId": {
|
|
2022
|
+
"type": "string",
|
|
2023
|
+
"pattern": "^[1-9]\\d{0,29}$",
|
|
2024
|
+
"description": "One advertiser's exact Facebook Page ID (from its Ad Library link, view_all_page_id)."
|
|
2025
|
+
},
|
|
2026
|
+
"country": {
|
|
2027
|
+
"type": "string",
|
|
2028
|
+
"enum": [
|
|
2029
|
+
"EU_UK",
|
|
2030
|
+
"AT",
|
|
2031
|
+
"BE",
|
|
2032
|
+
"BG",
|
|
2033
|
+
"HR",
|
|
2034
|
+
"CY",
|
|
2035
|
+
"CZ",
|
|
2036
|
+
"DK",
|
|
2037
|
+
"EE",
|
|
2038
|
+
"FI",
|
|
2039
|
+
"FR",
|
|
2040
|
+
"DE",
|
|
2041
|
+
"GR",
|
|
2042
|
+
"HU",
|
|
2043
|
+
"IE",
|
|
2044
|
+
"IT",
|
|
2045
|
+
"LV",
|
|
2046
|
+
"LT",
|
|
2047
|
+
"LU",
|
|
2048
|
+
"MT",
|
|
2049
|
+
"NL",
|
|
2050
|
+
"PL",
|
|
2051
|
+
"PT",
|
|
2052
|
+
"RO",
|
|
2053
|
+
"SK",
|
|
2054
|
+
"SI",
|
|
2055
|
+
"ES",
|
|
2056
|
+
"SE",
|
|
2057
|
+
"GB"
|
|
2058
|
+
],
|
|
2059
|
+
"default": "EU_UK",
|
|
2060
|
+
"description": "Where the ad was shown"
|
|
2061
|
+
},
|
|
2062
|
+
"mediaType": {
|
|
2063
|
+
"type": "string",
|
|
2064
|
+
"enum": [
|
|
2065
|
+
"ALL",
|
|
2066
|
+
"IMAGE",
|
|
2067
|
+
"VIDEO"
|
|
2068
|
+
],
|
|
2069
|
+
"default": "ALL"
|
|
2070
|
+
},
|
|
2071
|
+
"platform": {
|
|
2072
|
+
"type": "string",
|
|
2073
|
+
"enum": [
|
|
2074
|
+
"ALL",
|
|
2075
|
+
"FACEBOOK",
|
|
2076
|
+
"INSTAGRAM",
|
|
2077
|
+
"MESSENGER",
|
|
2078
|
+
"AUDIENCE_NETWORK",
|
|
2079
|
+
"THREADS",
|
|
2080
|
+
"WHATSAPP"
|
|
2081
|
+
],
|
|
2082
|
+
"default": "ALL"
|
|
2083
|
+
},
|
|
2084
|
+
"status": {
|
|
2085
|
+
"type": "string",
|
|
2086
|
+
"enum": [
|
|
2087
|
+
"ACTIVE",
|
|
2088
|
+
"INACTIVE",
|
|
2089
|
+
"ALL"
|
|
2090
|
+
],
|
|
2091
|
+
"default": "ACTIVE",
|
|
2092
|
+
"description": "ACTIVE: running now"
|
|
2093
|
+
},
|
|
2094
|
+
"cursor": {
|
|
2095
|
+
"type": "string",
|
|
2096
|
+
"format": "uuid",
|
|
2097
|
+
"description": "nextCursor from the previous page of the same search; keep every other parameter unchanged."
|
|
2098
|
+
}
|
|
2099
|
+
},
|
|
2100
|
+
"additionalProperties": false
|
|
2101
|
+
},
|
|
2102
|
+
"requestSchema": null,
|
|
2103
|
+
"requestExample": null,
|
|
2104
|
+
"responseExample": {
|
|
2105
|
+
"success": true,
|
|
2106
|
+
"data": {
|
|
2107
|
+
"items": [
|
|
2108
|
+
{
|
|
2109
|
+
"adId": "2716161098763684",
|
|
2110
|
+
"pageId": "123456789",
|
|
2111
|
+
"pageName": "Example brand",
|
|
2112
|
+
"bodies": [
|
|
2113
|
+
"Turn one idea into a week of videos."
|
|
2114
|
+
],
|
|
2115
|
+
"titles": [
|
|
2116
|
+
"Videos on autopilot"
|
|
2117
|
+
],
|
|
2118
|
+
"captions": [],
|
|
2119
|
+
"descriptions": [],
|
|
2120
|
+
"startedAt": "2026-08-01T00:00:00.000Z",
|
|
2121
|
+
"stoppedAt": null,
|
|
2122
|
+
"platforms": [
|
|
2123
|
+
"FACEBOOK",
|
|
2124
|
+
"INSTAGRAM"
|
|
2125
|
+
],
|
|
2126
|
+
"mediaType": null,
|
|
2127
|
+
"observedStatus": "ACTIVE",
|
|
2128
|
+
"sourceUrl": "https://www.facebook.com/ads/library/?id=2716161098763684",
|
|
2129
|
+
"fetchedAt": "2026-09-26T10:00:00.000Z",
|
|
2130
|
+
"savedId": null
|
|
2131
|
+
}
|
|
2132
|
+
],
|
|
2133
|
+
"resultToken": "22df1b25-533f-4bd7-862a-aedc4a4ea0cc",
|
|
2134
|
+
"expiresAt": "2026-09-26T10:15:00.000Z",
|
|
2135
|
+
"nextCursor": "0b6f3c1e-8f4a-4c55-9e0b-7d2a1c9e4f10"
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
"operationId": "listSavedAds",
|
|
2141
|
+
"method": "get",
|
|
2142
|
+
"path": "/saved-ads",
|
|
2143
|
+
"resource": "ads",
|
|
2144
|
+
"summary": "List the team's saved ads",
|
|
2145
|
+
"description": "Returns the ads the team saved from Meta Ad Library searches, newest first, 24 per page, with each ad's details as Meta showed them when it was saved. Filter by one advertiser with pageId. Works even when fresh search is paused.",
|
|
2146
|
+
"scopes": [
|
|
2147
|
+
"ads:read"
|
|
2148
|
+
],
|
|
2149
|
+
"status": 200,
|
|
2150
|
+
"idempotent": false,
|
|
2151
|
+
"terminalStates": null,
|
|
2152
|
+
"creditCost": "none",
|
|
2153
|
+
"cli": {
|
|
2154
|
+
"command": "ads saved"
|
|
2155
|
+
},
|
|
2156
|
+
"mcp": {
|
|
2157
|
+
"name": "faceless_list_saved_ads",
|
|
2158
|
+
"enabled": false
|
|
2159
|
+
},
|
|
2160
|
+
"querySchema": {
|
|
2161
|
+
"type": "object",
|
|
2162
|
+
"properties": {
|
|
2163
|
+
"pageId": {
|
|
2164
|
+
"type": "string",
|
|
2165
|
+
"pattern": "^[1-9]\\d{0,29}$",
|
|
2166
|
+
"description": "Only this advertiser's ads"
|
|
2167
|
+
},
|
|
2168
|
+
"page": {
|
|
2169
|
+
"type": "integer",
|
|
2170
|
+
"minimum": 1,
|
|
2171
|
+
"default": 1
|
|
2172
|
+
}
|
|
2173
|
+
},
|
|
2174
|
+
"additionalProperties": false
|
|
2175
|
+
},
|
|
2176
|
+
"requestSchema": null,
|
|
2177
|
+
"requestExample": null,
|
|
2178
|
+
"responseExample": {
|
|
2179
|
+
"success": true,
|
|
2180
|
+
"data": {
|
|
2181
|
+
"items": [
|
|
2182
|
+
{
|
|
2183
|
+
"id": "665f1b2a9c31a2b3c4d5f001",
|
|
2184
|
+
"ad": {
|
|
2185
|
+
"adId": "2716161098763684",
|
|
2186
|
+
"pageName": "Example brand"
|
|
2187
|
+
},
|
|
2188
|
+
"savedAt": "2026-09-26T10:01:00.000Z"
|
|
2189
|
+
}
|
|
2190
|
+
],
|
|
2191
|
+
"advertisers": [
|
|
2192
|
+
{
|
|
2193
|
+
"pageId": "123456789",
|
|
2194
|
+
"pageName": "Example brand"
|
|
2195
|
+
}
|
|
2196
|
+
],
|
|
2197
|
+
"savedCount": 1,
|
|
2198
|
+
"savedLimit": 500,
|
|
2199
|
+
"page": 1,
|
|
2200
|
+
"pages": 1
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
},
|
|
2204
|
+
{
|
|
2205
|
+
"operationId": "saveAd",
|
|
2206
|
+
"method": "post",
|
|
2207
|
+
"path": "/saved-ads",
|
|
2208
|
+
"resource": "ads",
|
|
2209
|
+
"summary": "Save an ad from a search",
|
|
2210
|
+
"description": "Saves one ad from a searchAds result to the team's saved ads, using that search's resultToken (valid 15 minutes; search again after that). Saving the same ad twice returns the first save. A team can keep 500 saved ads.",
|
|
2211
|
+
"scopes": [
|
|
2212
|
+
"ads:write"
|
|
2213
|
+
],
|
|
2214
|
+
"status": 200,
|
|
2215
|
+
"idempotent": false,
|
|
2216
|
+
"terminalStates": null,
|
|
2217
|
+
"creditCost": "none",
|
|
2218
|
+
"cli": {
|
|
2219
|
+
"command": "ads save"
|
|
2220
|
+
},
|
|
2221
|
+
"mcp": {
|
|
2222
|
+
"name": "faceless_save_ad",
|
|
2223
|
+
"enabled": false
|
|
2224
|
+
},
|
|
2225
|
+
"querySchema": null,
|
|
2226
|
+
"requestSchema": {
|
|
2227
|
+
"type": "object",
|
|
2228
|
+
"properties": {
|
|
2229
|
+
"adId": {
|
|
2230
|
+
"type": "string",
|
|
2231
|
+
"pattern": "^[1-9]\\d{0,29}$",
|
|
2232
|
+
"description": "adId from searchAds"
|
|
2233
|
+
},
|
|
2234
|
+
"resultToken": {
|
|
2235
|
+
"type": "string",
|
|
2236
|
+
"format": "uuid",
|
|
2237
|
+
"description": "resultToken of the search page that returned the ad"
|
|
2238
|
+
}
|
|
2239
|
+
},
|
|
2240
|
+
"required": [
|
|
2241
|
+
"adId",
|
|
2242
|
+
"resultToken"
|
|
2243
|
+
],
|
|
2244
|
+
"additionalProperties": false
|
|
2245
|
+
},
|
|
2246
|
+
"requestExample": {
|
|
2247
|
+
"adId": "2716161098763684",
|
|
2248
|
+
"resultToken": "22df1b25-533f-4bd7-862a-aedc4a4ea0cc"
|
|
2249
|
+
},
|
|
2250
|
+
"responseExample": {
|
|
2251
|
+
"success": true,
|
|
2252
|
+
"data": {
|
|
2253
|
+
"id": "665f1b2a9c31a2b3c4d5f001",
|
|
2254
|
+
"ad": {
|
|
2255
|
+
"adId": "2716161098763684",
|
|
2256
|
+
"pageName": "Example brand"
|
|
2257
|
+
},
|
|
2258
|
+
"savedAt": "2026-09-26T10:01:00.000Z"
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
},
|
|
2262
|
+
{
|
|
2263
|
+
"operationId": "deleteSavedAd",
|
|
2264
|
+
"method": "delete",
|
|
2265
|
+
"path": "/saved-ads/{id}",
|
|
2266
|
+
"resource": "ads",
|
|
2267
|
+
"summary": "Remove a saved ad",
|
|
2268
|
+
"description": "Removes one of the team's saved ads. An id the team does not have answers 404.",
|
|
2269
|
+
"scopes": [
|
|
2270
|
+
"ads:write"
|
|
2271
|
+
],
|
|
2272
|
+
"status": 200,
|
|
2273
|
+
"idempotent": false,
|
|
2274
|
+
"terminalStates": null,
|
|
2275
|
+
"creditCost": "none",
|
|
2276
|
+
"cli": {
|
|
2277
|
+
"command": "ads unsave"
|
|
2278
|
+
},
|
|
2279
|
+
"mcp": {
|
|
2280
|
+
"name": "faceless_delete_saved_ad",
|
|
2281
|
+
"enabled": false
|
|
2282
|
+
},
|
|
2283
|
+
"querySchema": null,
|
|
2284
|
+
"requestSchema": null,
|
|
2285
|
+
"requestExample": null,
|
|
2286
|
+
"responseExample": {
|
|
2287
|
+
"success": true,
|
|
2288
|
+
"data": {
|
|
2289
|
+
"deleted": true
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
},
|
|
2293
|
+
{
|
|
2294
|
+
"operationId": "createAdBrief",
|
|
2295
|
+
"method": "post",
|
|
2296
|
+
"path": "/ads/briefs",
|
|
2297
|
+
"resource": "ads",
|
|
2298
|
+
"summary": "Write an ad brief for your brand from a competitor's ad",
|
|
2299
|
+
"description": "Writes an original ad brief (hook, promise, script, visual direction, call to action) for the team's brand, inspired by one ad from searchAds or the saved ads. Only the ad's approach carries over: every claim comes from the brand description you send, and the advertiser's name, offers, prices and results never appear. target sizes the script: motion (20 s motion-graphics ad), product-video (30 s narrated video), ugc (20 s creator talking to camera) or image (one static ad). Free; use the brief with createVideo or any other operation. 30 briefs per hour.",
|
|
2300
|
+
"scopes": [
|
|
2301
|
+
"ads:write"
|
|
2302
|
+
],
|
|
2303
|
+
"status": 200,
|
|
2304
|
+
"idempotent": false,
|
|
2305
|
+
"terminalStates": null,
|
|
2306
|
+
"creditCost": "none",
|
|
2307
|
+
"cli": {
|
|
2308
|
+
"command": "ads brief"
|
|
2309
|
+
},
|
|
2310
|
+
"mcp": {
|
|
2311
|
+
"name": "faceless_create_ad_brief",
|
|
2312
|
+
"enabled": false
|
|
2313
|
+
},
|
|
2314
|
+
"querySchema": null,
|
|
2315
|
+
"requestSchema": {
|
|
2316
|
+
"type": "object",
|
|
2317
|
+
"properties": {
|
|
2318
|
+
"adId": {
|
|
2319
|
+
"type": "string",
|
|
2320
|
+
"pattern": "^[1-9]\\d{0,29}$"
|
|
2321
|
+
},
|
|
2322
|
+
"resultToken": {
|
|
2323
|
+
"type": "string",
|
|
2324
|
+
"format": "uuid",
|
|
2325
|
+
"description": "From searchAds; send this or savedId"
|
|
2326
|
+
},
|
|
2327
|
+
"savedId": {
|
|
2328
|
+
"type": "string",
|
|
2329
|
+
"pattern": "^[0-9a-fA-F]{24}$",
|
|
2330
|
+
"description": "A saved ad's id; send this or resultToken"
|
|
2331
|
+
},
|
|
2332
|
+
"target": {
|
|
2333
|
+
"type": "string",
|
|
2334
|
+
"enum": [
|
|
2335
|
+
"motion",
|
|
2336
|
+
"product-video",
|
|
2337
|
+
"ugc",
|
|
2338
|
+
"image"
|
|
2339
|
+
],
|
|
2340
|
+
"description": "What the brief is for"
|
|
2341
|
+
},
|
|
2342
|
+
"brand": {
|
|
2343
|
+
"type": "object",
|
|
2344
|
+
"properties": {
|
|
2345
|
+
"name": {
|
|
2346
|
+
"type": "string",
|
|
2347
|
+
"minLength": 1,
|
|
2348
|
+
"maxLength": 120
|
|
2349
|
+
},
|
|
2350
|
+
"description": {
|
|
2351
|
+
"type": "string",
|
|
2352
|
+
"minLength": 20,
|
|
2353
|
+
"maxLength": 1500,
|
|
2354
|
+
"description": "What you sell and who it is for. The only source of claims."
|
|
2355
|
+
},
|
|
2356
|
+
"website": {
|
|
2357
|
+
"type": "string",
|
|
2358
|
+
"maxLength": 300
|
|
2359
|
+
}
|
|
2360
|
+
},
|
|
2361
|
+
"required": [
|
|
2362
|
+
"name",
|
|
2363
|
+
"description"
|
|
2364
|
+
],
|
|
2365
|
+
"additionalProperties": false,
|
|
2366
|
+
"description": "Your brand"
|
|
2367
|
+
},
|
|
2368
|
+
"notes": {
|
|
2369
|
+
"type": "string",
|
|
2370
|
+
"maxLength": 600,
|
|
2371
|
+
"description": "A real offer, a feature to lead with, a tone"
|
|
2372
|
+
}
|
|
2373
|
+
},
|
|
2374
|
+
"required": [
|
|
2375
|
+
"adId",
|
|
2376
|
+
"target",
|
|
2377
|
+
"brand"
|
|
2378
|
+
],
|
|
2379
|
+
"additionalProperties": false
|
|
2380
|
+
},
|
|
2381
|
+
"requestExample": {
|
|
2382
|
+
"adId": "2716161098763684",
|
|
2383
|
+
"resultToken": "22df1b25-533f-4bd7-862a-aedc4a4ea0cc",
|
|
2384
|
+
"target": "product-video",
|
|
2385
|
+
"brand": {
|
|
2386
|
+
"name": "Acme Coffee",
|
|
2387
|
+
"description": "Small-batch coffee beans roasted to order and shipped within two days."
|
|
2388
|
+
}
|
|
2389
|
+
},
|
|
2390
|
+
"responseExample": {
|
|
2391
|
+
"success": true,
|
|
2392
|
+
"data": {
|
|
2393
|
+
"brief": {
|
|
2394
|
+
"hook": "Your coffee was roasted months ago",
|
|
2395
|
+
"benefit": "Beans roasted the day you order them, at your door two days later.",
|
|
2396
|
+
"script": "Your coffee was roasted months ago. Ours is roasted when you order. It reaches you two days later. Taste the difference.",
|
|
2397
|
+
"visualDirection": "Close-ups of beans leaving the roaster, a kraft bag being sealed, a morning pour.",
|
|
2398
|
+
"cta": "Order a fresh bag"
|
|
2399
|
+
},
|
|
2400
|
+
"source": {
|
|
2401
|
+
"adId": "2716161098763684",
|
|
2402
|
+
"pageName": "Example brand",
|
|
2403
|
+
"sourceUrl": "https://www.facebook.com/ads/library/?id=2716161098763684"
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
1929
2407
|
}
|
|
1930
2408
|
]
|
|
1931
2409
|
}
|
package/src/index.mjs
CHANGED
|
@@ -286,6 +286,16 @@ program
|
|
|
286
286
|
print(result, { json: cmd.optsWithGlobals().json });
|
|
287
287
|
});
|
|
288
288
|
|
|
289
|
+
program
|
|
290
|
+
.command("buy-credits")
|
|
291
|
+
.description(getOp("buyCredits").summary)
|
|
292
|
+
.requiredOption("--pack <id>", "credit pack: pack_10, pack_25 or pack_50")
|
|
293
|
+
.requiredOption("--token <spt>", "Stripe Shared Payment Token (spt_...) from your agent wallet")
|
|
294
|
+
.action(async (opts, cmd) => {
|
|
295
|
+
const result = await execute("buyCredits", { body: { packId: opts.pack, paymentToken: opts.token } }, cmd);
|
|
296
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
297
|
+
});
|
|
298
|
+
|
|
289
299
|
const videos = program.command("videos").description("Faceless video projects");
|
|
290
300
|
|
|
291
301
|
withWaitFlags(
|
|
@@ -669,6 +679,76 @@ program
|
|
|
669
679
|
print(result, { json: cmd.optsWithGlobals().json });
|
|
670
680
|
});
|
|
671
681
|
|
|
682
|
+
const ads = program.command("ads").description("Meta Ad Library: search competitor ads, keep the good ones, brief your own");
|
|
683
|
+
|
|
684
|
+
ads.command("search [keywords]")
|
|
685
|
+
.description(getOp("searchAds").summary)
|
|
686
|
+
.option("--page-id <id>", "one advertiser's Facebook Page ID instead of keywords")
|
|
687
|
+
.option("--country <code>", "EU_UK (default) or one EU/UK country code, e.g. DE")
|
|
688
|
+
.addOption(new Option("--media <type>", "media type").choices(["ALL", "IMAGE", "VIDEO"]))
|
|
689
|
+
.option("--platform <name>", "ALL (default), FACEBOOK, INSTAGRAM, MESSENGER, AUDIENCE_NETWORK, THREADS or WHATSAPP")
|
|
690
|
+
.addOption(new Option("--status <status>", "delivery status").choices(["ACTIVE", "INACTIVE", "ALL"]))
|
|
691
|
+
.option("--cursor <cursor>", "nextCursor from the previous page of the same search")
|
|
692
|
+
.action(async (keywords, opts, cmd) => {
|
|
693
|
+
const query = {
|
|
694
|
+
q: keywords,
|
|
695
|
+
pageId: opts.pageId,
|
|
696
|
+
country: opts.country,
|
|
697
|
+
mediaType: opts.media,
|
|
698
|
+
platform: opts.platform,
|
|
699
|
+
status: opts.status,
|
|
700
|
+
cursor: opts.cursor,
|
|
701
|
+
};
|
|
702
|
+
const result = await execute("searchAds", { query }, cmd);
|
|
703
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
ads.command("saved")
|
|
707
|
+
.description(getOp("listSavedAds").summary)
|
|
708
|
+
.option("--page-id <id>", "only this advertiser's ads")
|
|
709
|
+
.option("--page <n>", "page number", toInt)
|
|
710
|
+
.action(async (opts, cmd) => {
|
|
711
|
+
const result = await execute("listSavedAds", { query: { pageId: opts.pageId, page: opts.page } }, cmd);
|
|
712
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
ads.command("save <adId>")
|
|
716
|
+
.description(getOp("saveAd").summary)
|
|
717
|
+
.requiredOption("--result-token <token>", "resultToken from the search that returned the ad")
|
|
718
|
+
.action(async (adId, opts, cmd) => {
|
|
719
|
+
const result = await execute("saveAd", { body: { adId, resultToken: opts.resultToken } }, cmd);
|
|
720
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
ads.command("unsave <savedId>")
|
|
724
|
+
.description(getOp("deleteSavedAd").summary)
|
|
725
|
+
.action(async (id, _opts, cmd) => {
|
|
726
|
+
const result = await execute("deleteSavedAd", { pathParams: { id } }, cmd);
|
|
727
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
ads.command("brief <adId>")
|
|
731
|
+
.description(getOp("createAdBrief").summary)
|
|
732
|
+
.addOption(new Option("--target <target>", "what the brief is for").choices(["motion", "product-video", "ugc", "image"]).makeOptionMandatory())
|
|
733
|
+
.requiredOption("--brand <name>", "your brand or product name")
|
|
734
|
+
.requiredOption("--about <text>", "what you sell and who it is for (the only source of claims)")
|
|
735
|
+
.option("--website <url>", "your website")
|
|
736
|
+
.option("--result-token <token>", "resultToken from searchAds (or use --saved-id)")
|
|
737
|
+
.option("--saved-id <id>", "a saved ad's id (or use --result-token)")
|
|
738
|
+
.option("--notes <text>", "a real offer, a feature to lead with, a tone")
|
|
739
|
+
.action(async (adId, opts, cmd) => {
|
|
740
|
+
const body = {
|
|
741
|
+
adId,
|
|
742
|
+
resultToken: opts.resultToken,
|
|
743
|
+
savedId: opts.savedId,
|
|
744
|
+
target: opts.target,
|
|
745
|
+
brand: compact({ name: opts.brand, description: opts.about, website: opts.website }),
|
|
746
|
+
notes: opts.notes,
|
|
747
|
+
};
|
|
748
|
+
const result = await execute("createAdBrief", { body }, cmd);
|
|
749
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
750
|
+
});
|
|
751
|
+
|
|
672
752
|
program
|
|
673
753
|
.command("mcp")
|
|
674
754
|
.description("Start the local Faceless MCP server over stdio")
|