Skip to main content ホーム クリエイター comeonoliver skillshub adobe-known-pitfalls
adobe-known-pitfalls Identify and avoid Adobe-specific anti-patterns: using deprecated JWT auth,
not caching IMS tokens, ignoring Firefly content policy, missing async job
polling, and leaking p8_ secrets. Real code examples with fixes.
Trigger with phrases like "adobe mistakes", "adobe anti-patterns",
"adobe pitfalls", "adobe what not to do", "adobe code review".
インストールへ移動 Skills Marketplace コミュニティが作成したAIスキルを発見・探索
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/ComeOnOliver/skillshub --skill adobe-known-pitfallsコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Zipをダウンロード ダウンロード中... このリポジトリの他の Skills Review product and feature risk before an AI coding agent starts implementation.
Use Xquik for X data and confirmation-gated X actions: tweet search, user lookup, follower export, media download, monitors, webhooks, MCP, and SDK workflows.
Canton Network open-source ecosystem guide covering DAML SDK, Canton runtime, and Splice applications. Use when working with Canton Network, DAML smart contracts, or building decentralized applications.
name adobe-known-pitfalls description Identify and avoid Adobe-specific anti-patterns: using deprecated JWT auth,
not caching IMS tokens, ignoring Firefly content policy, missing async job
polling, and leaking p8_ secrets. Real code examples with fixes.
Trigger with phrases like "adobe mistakes", "adobe anti-patterns",
"adobe pitfalls", "adobe what not to do", "adobe code review".
allowed-tools Read, Grep version 1.0.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","design","adobe"] compatible-with claude-code
Adobe Known Pitfalls
Overview
The 10 most common mistakes when integrating with Adobe APIs, based on real production issues. Each pitfall includes the anti-pattern, why it fails, and the correct approach.
Prerequisites
Access to your Adobe integration codebase
Understanding of Adobe API architecture (OAuth, async jobs, rate limits)
Instructions
Pitfall 1: Still Using JWT (Service Account) Credentials
Status: CRITICAL — JWT credentials reached End of Life June 2025.
import jwt from 'jsonwebtoken' ;
import fs from 'fs' ;
const privateKey = fs.readFileSync ('private.key' );
const jwtToken = jwt.sign ({
exp : Math .round (Date .now () / 1000 ) + 86400 ,
iss : orgId,
sub : technicalAccountId,
aud : `https://ims-na1.adobelogin.com/c/${clientId} ` ,
}, privateKey, { algorithm : 'RS256' });
const res = await fetch ('https://ims-na1.adobelogin.com/ims/token/v3' , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/x-www-form-urlencoded' },
body : new URLSearchParams ({
: process. . !,
: process. . !,
: ,
: process. . !,
}),
});
client_id
env
ADOBE_CLIENT_ID
client_secret
env
ADOBE_CLIENT_SECRET
grant_type
'client_credentials'
scope
env
ADOBE_SCOPES
Pitfall 2: Not Caching IMS Access Tokens IMS tokens are valid for 24 hours. Generating a new token per request wastes 200-500ms:
async function callFirefly (prompt : string ) {
const tokenRes = await fetch ('https://ims-na1.adobelogin.com/ims/token/v3' , { ... });
const { access_token } = await tokenRes.json ();
}
let cached : { token : string ; expiresAt : number } | null = null ;
async function getToken ( ): Promise <string > {
if (cached && cached.expiresAt > Date .now () + 300_000 ) return cached.token ;
const res = await fetch ('https://ims-na1.adobelogin.com/ims/token/v3' , { ... });
const data = await res.json ();
cached = { token : data.access_token , expiresAt : Date .now () + data.expires_in * 1000 };
return cached.token ;
}
Pitfall 3: Using Firefly Sync Endpoint for Batch Operations
for (const prompt of prompts) {
const result = await fetch ('https://firefly-api.adobe.io/v3/images/generate' , {
method : 'POST' , ...
});
results.push (await result.json ());
}
const jobs = await Promise .all (
prompts.map (prompt =>
fetch ('https://firefly-api.adobe.io/v3/images/generate-async' , {
method : 'POST' , ...
}).then (r => r.json ())
)
);
const results = await Promise .all (jobs.map (j => pollJob (j.statusUrl )));
Pitfall 4: Ignoring Firefly Content Policy Errors
try {
const result = await generateImage ({ prompt : 'Photo of Nike shoes' });
} catch (e) {
console .log ('Generation failed' );
}
try {
const result = await generateImage ({ prompt });
} catch (e : any ) {
if (e.status === 400 && e.message ?.includes ('content policy' )) {
throw new Error (
'Firefly content policy violation. ' +
'Remove trademarks, real people, or explicit content from prompt.'
);
}
throw e;
}
Pitfall 5: Uploading Files Directly to Photoshop/Lightroom API
const formData = new FormData ();
formData.append ('image' , fs.readFileSync ('photo.jpg' ));
await fetch ('https://image.adobe.io/v2/remove-background' , {
method : 'POST' ,
body : formData,
});
const inputUrl = await s3.getSignedUrl ('getObject' , {
Bucket : 'my-bucket' , Key : 'photo.jpg' , Expires : 3600 ,
});
const outputUrl = await s3.getSignedUrl ('putObject' , {
Bucket : 'my-bucket' , Key : 'output.png' , Expires : 3600 ,
});
await fetch ('https://image.adobe.io/v2/remove-background' , {
method : 'POST' ,
headers : { Authorization : `Bearer ${token} ` , 'x-api-key' : clientId, 'Content-Type' : 'application/json' },
body : JSON .stringify ({
input : { href : inputUrl, storage : 'external' },
output : { href : outputUrl, storage : 'external' , type : 'image/png' },
}),
});
Pitfall 6: Not Polling Async Job Status Photoshop and Lightroom APIs return immediately with a job ID. You must poll for results:
const res = await fetch ('https://image.adobe.io/v2/remove-background' , { ... });
const result = await res.json ();
console .log ('Done!' , result);
const submission = await res.json ();
let job;
do {
await new Promise (r => setTimeout (r, 2000 ));
const pollRes = await fetch (submission._links .self .href , {
headers : { Authorization : `Bearer ${token} ` , 'x-api-key' : clientId },
});
job = await pollRes.json ();
} while (job.status !== 'succeeded' && job.status !== 'failed' );
if (job.status === 'failed' ) throw new Error (job.error ?.message );
Pitfall 7: Leaking Adobe Credentials in Source Code
const client_secret = 'p8_XYZ_your_actual_secret_here_do_not_do_this' ;
const client_secret = process.env .ADOBE_CLIENT_SECRET !;
Pitfall 8: Not Handling PDF Services Quota
async function extractAllPdfs (paths : string [] ) {
for (const path of paths) {
await extractPdf (path);
}
}
let txCount = 0 ;
async function trackedExtract (path : string ) {
if (txCount >= 490 ) {
throw new Error ('Approaching PDF Services monthly limit. 10 transactions remaining.' );
}
const result = await extractPdf (path);
txCount++;
return result;
}
Pitfall 9: Using Deprecated Photoshop Endpoints
await fetch ('https://image.adobe.io/sensei/cutout' , { ... });
await fetch ('https://image.adobe.io/v2/remove-background' , { ... });
Pitfall 10: Missing Webhook Signature Verification
app.post ('/webhooks/adobe' , (req, res ) => {
processEvent (req.body );
res.sendStatus (200 );
});
app.post ('/webhooks/adobe' , express.raw ({ type : 'application/json' }), async (req, res) => {
const sig = req.headers ['x-adobe-digital-signature-1' ];
const keyPath = req.headers ['x-adobe-public-key1-path' ];
const publicKey = await fetch (`https://static.adobeioevents.com${keyPath} ` ).then (r => r.text ());
const verifier = crypto.createVerify ('RSA-SHA256' );
verifier.update (req.body );
if (!verifier.verify (publicKey, sig, 'base64' )) {
return res.sendStatus (401 );
}
processEvent (JSON .parse (req.body .toString ()));
res.sendStatus (200 );
});
Quick Pitfall Scanner
echo "=== Adobe Pitfall Scan ==="
grep -rn "jsonwebtoken\|jwt\.sign\|RS256" --include="*.ts" --include="*.js" src/ && echo "FOUND: JWT auth (deprecated)" || echo "OK: No JWT"
grep -rn "ims/token/v3" --include="*.ts" src/ | wc -l | xargs -I{} echo "Token endpoint calls: {} (should be 1 — in auth.ts only)"
grep -rn "p8_" --include="*.ts" --include="*.js" src/ && echo "FOUND: Hardcoded Adobe secret" || echo "OK: No hardcoded secrets"
grep -rn "sensei/cutout" --include="*.ts" src/ && echo "FOUND: Deprecated Photoshop endpoint" || echo "OK: No deprecated endpoints"
grep -rn "webhooks/adobe" --include="*.ts" src/ | grep -v "digital-signature\|verify\|RSA" && echo "WARNING: Webhook handler may lack signature verification"
Quick Reference Card Pitfall Risk Detection Fix JWT auth Broken auth Grep for jwt.sign Migrate to OAuth S2S No token cache Perf (-500ms/req) Multiple ims/token calls Cache with expiry Sync Firefly for batch Slow (N*20s) Sequential generate calls Use async endpoint Ignore content policy Wasted credits Catch 400 without reason Pre-screen prompts Direct file upload 400 errors FormData to Photoshop Pre-signed URLs No job polling Missing results No poll loop after submit Poll _links.self Leaked p8_ secret Credential compromise Grep for p8_ Env vars + .gitignore No quota tracking Silent failures No counter Track per-month usage Old PS endpoint 404 errors /sensei/cutout/v2/remove-backgroundNo webhook verify Security hole No signature check RSA-SHA256 verification
Resources