fix: correct API issues found by codex review across 10 CLIs
Fixes found by automated codex review of all 47 CLI tools: - resend: webhook field name endpoint_url -> endpoint - mailchimp: change from Bearer to Basic auth per API docs - kit: fail fast when api_secret required but not set - activecampaign: automation add-contact needs --contact-id not --email - google-ads: budget updateMask must be snake_case (amount_micros) - meta-ads: special_ad_categories default to ['NONE'] not empty array - linkedin-ads: add required X-RestLi-Protocol-Version header - onesignal: auth prefix should be Key, not Basic - mixpanel: query dates must be YYYY-MM-DD, not relative strings - wistia: change from Bearer to Basic auth per API docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8ce007c983
commit
f123804827
10 changed files with 18 additions and 11 deletions
|
|
@ -273,11 +273,11 @@ async function main() {
|
||||||
}
|
}
|
||||||
case 'add-contact': {
|
case 'add-contact': {
|
||||||
const automationId = args.id
|
const automationId = args.id
|
||||||
const contactEmail = args.email
|
const contactId = args['contact-id']
|
||||||
if (!automationId) { result = { error: '--id required (automation ID)' }; break }
|
if (!automationId) { result = { error: '--id required (automation ID)' }; break }
|
||||||
if (!contactEmail) { result = { error: '--email required' }; break }
|
if (!contactId) { result = { error: '--contact-id required (contact ID, not email)' }; break }
|
||||||
result = await api('POST', '/contactAutomations', {
|
result = await api('POST', '/contactAutomations', {
|
||||||
contactAutomation: { contact: contactEmail, automation: automationId }
|
contactAutomation: { contact: contactId, automation: automationId }
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ async function main() {
|
||||||
resourceName: `customers/${CUSTOMER_ID}/campaignBudgets/${args.id}`,
|
resourceName: `customers/${CUSTOMER_ID}/campaignBudgets/${args.id}`,
|
||||||
amountMicros,
|
amountMicros,
|
||||||
},
|
},
|
||||||
updateMask: 'amountMicros',
|
updateMask: 'amount_micros',
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ async function api(method, path, body, useSecret = true) {
|
||||||
if (method === 'GET' || method === 'DELETE') {
|
if (method === 'GET' || method === 'DELETE') {
|
||||||
if (useSecret && API_SECRET) {
|
if (useSecret && API_SECRET) {
|
||||||
url.searchParams.set('api_secret', API_SECRET)
|
url.searchParams.set('api_secret', API_SECRET)
|
||||||
|
} else if (useSecret && !API_SECRET) {
|
||||||
|
return { error: 'KIT_API_SECRET required for this endpoint' }
|
||||||
} else if (API_KEY) {
|
} else if (API_KEY) {
|
||||||
url.searchParams.set('api_key', API_KEY)
|
url.searchParams.set('api_key', API_KEY)
|
||||||
}
|
}
|
||||||
|
|
@ -26,6 +28,8 @@ async function api(method, path, body, useSecret = true) {
|
||||||
const authBody = { ...body }
|
const authBody = { ...body }
|
||||||
if (useSecret && API_SECRET) {
|
if (useSecret && API_SECRET) {
|
||||||
authBody.api_secret = API_SECRET
|
authBody.api_secret = API_SECRET
|
||||||
|
} else if (useSecret && !API_SECRET) {
|
||||||
|
return { error: 'KIT_API_SECRET required for this endpoint' }
|
||||||
} else if (API_KEY) {
|
} else if (API_KEY) {
|
||||||
authBody.api_key = API_KEY
|
authBody.api_key = API_KEY
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ if (!TOKEN) {
|
||||||
async function api(method, path, body) {
|
async function api(method, path, body) {
|
||||||
const headers = {
|
const headers = {
|
||||||
'Authorization': `Bearer ${TOKEN}`,
|
'Authorization': `Bearer ${TOKEN}`,
|
||||||
|
'X-RestLi-Protocol-Version': '2.0.0',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
if (args['dry-run']) {
|
if (args['dry-run']) {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,9 @@ const dc = API_KEY.split('-').pop()
|
||||||
const BASE_URL = `https://${dc}.api.mailchimp.com/3.0`
|
const BASE_URL = `https://${dc}.api.mailchimp.com/3.0`
|
||||||
|
|
||||||
async function api(method, path, body) {
|
async function api(method, path, body) {
|
||||||
|
const auth = 'Basic ' + Buffer.from(`anystring:${API_KEY}`).toString('base64')
|
||||||
const headers = {
|
const headers = {
|
||||||
'Authorization': `Bearer ${API_KEY}`,
|
'Authorization': auth,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
if (args['dry-run']) {
|
if (args['dry-run']) {
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ async function main() {
|
||||||
name: args.name,
|
name: args.name,
|
||||||
objective: args.objective,
|
objective: args.objective,
|
||||||
status: args.status || 'PAUSED',
|
status: args.status || 'PAUSED',
|
||||||
special_ad_categories: [],
|
special_ad_categories: ['NONE'],
|
||||||
}
|
}
|
||||||
result = await api('POST', `/act_${accountId}/campaigns`, body)
|
result = await api('POST', `/act_${accountId}/campaigns`, body)
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -155,8 +155,8 @@ async function main() {
|
||||||
params: {
|
params: {
|
||||||
events: [{ event: args.event || 'all' }],
|
events: [{ event: args.event || 'all' }],
|
||||||
time_range: {
|
time_range: {
|
||||||
from_date: args['from-date'] || '30daysAgo',
|
from_date: args['from-date'] || new Date(Date.now() - 30 * 86400000).toISOString().slice(0, 10),
|
||||||
to_date: args['to-date'] || 'today',
|
to_date: args['to-date'] || new Date().toISOString().slice(0, 10),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ if (!APP_ID) {
|
||||||
|
|
||||||
async function api(method, path, body) {
|
async function api(method, path, body) {
|
||||||
const headers = {
|
const headers = {
|
||||||
'Authorization': `Basic ${REST_API_KEY}`,
|
'Authorization': `Key ${REST_API_KEY}`,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ async function main() {
|
||||||
break
|
break
|
||||||
case 'create': {
|
case 'create': {
|
||||||
const events = args.events?.split(',') || ['email.sent', 'email.delivered', 'email.bounced']
|
const events = args.events?.split(',') || ['email.sent', 'email.delivered', 'email.bounced']
|
||||||
result = await api('POST', '/webhooks', { endpoint_url: args.endpoint, events })
|
result = await api('POST', '/webhooks', { endpoint: args.endpoint, events })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'delete':
|
case 'delete':
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@ if (!API_KEY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function api(method, path, body) {
|
async function api(method, path, body) {
|
||||||
|
const auth = 'Basic ' + Buffer.from(`${API_KEY}:`).toString('base64')
|
||||||
if (args['dry-run']) {
|
if (args['dry-run']) {
|
||||||
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'Authorization': '***', 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: body || undefined }
|
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'Authorization': '***', 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: body || undefined }
|
||||||
}
|
}
|
||||||
const res = await fetch(`${BASE_URL}${path}`, {
|
const res = await fetch(`${BASE_URL}${path}`, {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${API_KEY}`,
|
'Authorization': auth,
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue