Manifest Response Format (V1 to V2)
This guide covers every field-level change in the /v2/generate-manifest response. For request format migration (how to call the API), see the Manifest Migration guide.
Overview
The V2 manifest response is significantly richer than V1. The changes fall into these categories:
bounds format, blendOptions extensions, pixelMask restructure, thumbnail objectadjustments.type discriminant + per-type restructuringbackground_layer; new sub-fields; no typeAttributeslayerSection, new typeAttributes, layers[] vs children[]characterStyles, paragraphAttributes rename, enriched frame objectdata-variant=warning
data-slots=text
type strings changed (e.g. "adjustmentLayer" → "adjustment_layer"). Any code that switches on type must be updated. See Layer type taxonomy for the full rename table.Document-level fields
CHANGED — The old manifest had a document sub-object with different field names. The new format has a richer top-level document object.
Field renames
bitDepthdepthiccProfileNameiccProfilenametitleheight + widthbounds{left, top, right, bottom} objectphotoshopBuildNew document fields
bounds{left, top, right, bottom}imageMode"rgb"depth8iccProfile"sRGB IEC61966-2.1"xmptitle"filename.psd"globalLightingAngleglobalLightingAltitudelayerFXVisiblepixelScaleFactorresolution{value, unit}Layer type taxonomy
data-variant=warning
data-slots=text
if/else chains that compare layer.type must be updated.CHANGED — Type names renamed to snake_case; artboards promoted to a distinct type.
adjustmentLayeradjustment_layerbackgroundLayerbackground_layerfillLayersolid_color_layerlayerlayerlayerSectiongroup_layersmartObjectsmart_object_layertextLayertext_layerIn the old format, artboards were layerSection nodes indistinguishable from regular groups. The new format promotes artboards to type: "artboard" with dedicated typeAttributes.artboard data.
Per-layer common fields
bounds — CHANGED format
data-variant=warning
data-slots=text
bounds object no longer uses height/width. Computed dimensions must now be derived from right - left and bottom - top.Old format uses {height, left, top, width}:
{ "height": 200, "left": 10, "top": 20, "width": 300 }
New format uses {left, top, right, bottom} (no height/width):
{ "left": 10, "top": 20, "right": 310, "bottom": 220 }
thumbnail — CHANGED (restructured)
data-variant=warning
data-slots=text
thumbnail is no longer a plain string URL. Code that treats it as a string will break.Old format: plain string (pre-signed S3 URL):
"thumbnail": "https://s3.amazonaws.com/..."
New format: object with media type and short-URL:
"thumbnail": {
"mediaType": "image/jpeg",
"url": "https://photoshop-api.adobe.io/v2/short-url/urn:aaid:ps:..."
}
The thumbnail is optional — only present when the caller requests thumbnails. The URL is now a /v2/short-url/ redirect rather than a direct S3 URL.
Children nesting key — CHANGED
- Old: all nested layers use
children[]at every level - New: groups use
children[]; artboards uselayers[]for their children (see Artboard structure)
blendOptions — CHANGED (extended)
Old blendOptions only carried {blendMode, opacity}.
New blendOptions adds:
clippedinteriorfillOpacitypixelMaskAsGlobalMaskvectorMaskAsGlobalMasktransparencyShapesLayerknockout"none"channelRestrictionsblendRangespixelMask — CHANGED (was mask)
Old format uses a mask field at the layer level:
"mask": {
"enabled": true,
"linked": true,
"offset": { "x": 0, "y": 0 },
"type": "layer"
}
New format renames and restructures this as pixelMask (can be null or populated):
"pixelMask": {
"hasMask": true,
"extendOpaque": true,
"bounds": { "left": 0, "top": 0, "right": 2100, "bottom": 1500 },
"enabled": true,
"linked": true,
"offset": { "horizontal": 0, "vertical": 0 }
}
mask → pixelMasktype: "layer" removedextendOpaque (NEW)bounds (NEW){left,top,right,bottom}offset.x → offset.horizontal, offset.y → offset.verticalFields removed in V2
lockedprotection arrayrotaterotation (renamed)maskpixelMask (see above)thumbnailthumbnail object {mediaType, url}New fields in V2 only
protectionlocked; e.g. ["none"], ["position"], ["all"]rotationrotate (renamed)linkeduserMask{density, feather} — user mask statevectorMask{hasMask, bounds} — vector maskpixelMaskmask fieldproportionalScalingeffectscompositeFrame{absolute: {l,t,r,b}, relative: {l,t,r,b}} — canvas-space and parent-relative composite boundsreferenceFrame{left, top, right, bottom} — untransformed layer content boundscompositeDimensions{left, top, right, bottom} — enclosing artboard/document boundslayerSettingsAdjustment layers
Type rename: adjustmentLayer → adjustment_layer
adjustments block — CHANGED (restructured with type discriminant)
Old format uses a camelCase sub-object key per adjustment type:
{ "adjustments": { "vibrance": { "saturation": -24, "vibrance": 15 } } }
{ "adjustments": { "brightnessContrast": { "brightness": 18, "contrast": 36 } } }
New format adds a type discriminant (snake_case) and restructures some sub-fields:
{ "adjustments": { "type": "vibrance", "vibrance": 15, "saturation": -24 } }
{ "adjustments": { "type": "brightness_contrast", "brightnessContrast": { "brightness": 18, "contrast": 36 } } }
Per-type change summary
type)vibrance / vibranceadjustments.vibrance.{saturation,vibrance} → adjustments.{vibrance,saturation} (flat)exposure / exposureexposure value renamed to exposureValue; all values now nested under exposure sub-objecthueSaturation / hue_saturationchannels[].channel ("master") → hueSaturationAdjustments[]; per-channel ranges use new localRange fieldsbrightnessContrast / brightness_contrastcenter and useLegacycolorBalance / color_balancelevels / levelslevels.adjustment[] array with typed levelsAdjustment objectscurvesadjustments[] with channel and curves[{horizontal,vertical}]gradient_map_custom_stopscolorStops, transparencyStops, interpolationBackground layer
Type rename: backgroundLayer → background_layer
The background layer in the new format carries additional sub-fields not present in the old format. Background layer entries do not include typeAttributes (they match other layer types such as text, group, and adjustment).
backgroundLayertrue — explicitly marks this as the background layerbackground.canConvertToLayertrue — indicates the background can be promoted to a regular layerExample V2 background layer:
{
"type": "background_layer",
"id": 1,
"name": "Background",
"backgroundLayer": true,
"background": {
"canConvertToLayer": true
}
}
Fill / solid color layer
Type rename: fillLayer → solid_color_layer
fill.solidColor.rgb — unchanged
Both old and new use identical structure and value range (8-bit, 0–255):
{ "red": 255, "green": 0, "blue": 0 }
Vector mask — NEW in V2
Old fillLayer had no vector mask information. New solid_color_layer exposes:
{
"vectorMask": {
"hasMask": true,
"bounds": { "left": 0, "top": 0, "right": 500, "bottom": 500 }
}
}
layerSettings.vectorMask may also carry offset sub-data for the mask.
Artboard structure
data-variant=warning
data-slots=text
layers[] in V2, not children[]. Recursive traversal code must handle both keys.Old format — no distinct artboard type
Artboards were plain layerSection nodes, indistinguishable from regular groups:
{
"type": "layerSection",
"id": 1,
"name": "iPhone 16 Pro – 1",
"children": [ ... ]
}
New format — distinct artboard type with rich metadata
{
"type": "artboard",
"id": 1,
"name": "iPhone 16 Pro – 1",
"typeAttributes": {
"artboard": {
"type": "artboard",
"artboardBackgroundType": 1,
"artboardPresetName": "iPhone 16 Pro",
"artboardRect": {
"type": "classFloatRect",
"left": 0,
"top": 0,
"right": 393,
"bottom": 852
},
"color": {
"type": "RGBColor",
"red": 255,
"grain": 255,
"blue": 255
},
"guideIDs": []
},
"layerSection": "layerSectionStart",
"type": "layerSection"
},
"layers": [ ... ]
}
New artboard-specific fields
typeAttributes.artboard.artboardBackgroundTypetypeAttributes.artboard.artboardPresetName"iPhone 16 Pro")typeAttributes.artboard.artboardRect{type, left, top, right, bottom} — artboard geometrytypeAttributes.artboard.color{type, red, grain, blue} — background colortypeAttributes.artboard.guideIDstypeAttributes.layerSection"layerSectionStart" — dual typing retained for compatibilitytypeAttributes.type"layerSection" — inner discriminantChildren key difference
children[]children[]layers[]Smart object detail
Old smartObject block
{
"instanceId": "16da7404-...",
"linked": false,
"name": "foo.psd",
"path": "foo.psd",
"type": "image/vnd.adobe.photoshop"
}
New smart object block (heavily restructured)
{
"isSmartObject": true,
"isLinked": false,
"isValid": true,
"smartObjectData": {
"type": "smartObject",
"transform": [x0, y0, x1, y1, x2, y2, x3, y3],
"fileInfo": {
"name": "foo.psd",
"path": "foo.psd",
"fileType": "ps3",
"linked": false
}
},
"extracted": {
"mediaType": "application/octet-stream",
"url": "https://photoshop-api.adobe.io/v2/short-url/urn:..."
}
}
extracted is only present for non-linked (embedded) smart objects. ccLibrariesElement inside fileInfo is only present for CC Library-linked assets.
Field-by-field comparison
instanceIdfileInfolinkedisLinkednamesmartObjectData.fileInfo.namefileInfopathsmartObjectData.fileInfo.pathfileInfotype (MIME)smartObjectData.fileInfo.fileType"ps3", "unknown")isSmartObjectisValidsmartObjectData.transform[x0,y0, x1,y1, x2,y2, x3,y3]extracted.mediaType + .urlText layer detail
Character styles — CHANGED and NEW
Old characterStyles fields:
{
"fontAvailable": true,
"fontColor": { "rgb": { "red": 0, "green": 0, "blue": 0 } },
"fontName": "PostScriptName",
"fontSize": 12,
"orientation": "horizontal"
}
New characterStyles fields:
font.postScriptNamefont objectfont.isAvailablefontAvailable, now nested under fontfontSizefontColor.rgb.{red,green,blue}fontAlphasyntheticBoldsyntheticItalicunderlinecapsOption"normal_caps"lineHeightletterSpacingposition{from, to} — character range this style applies toorientation (old) is no longer a per-character-style field; it is now textOrientation at the text object level.
Paragraph styles — CHANGED and NEW
Old array was paragraphStyles:
[{ "alignment": "left" }]
New array is paragraphAttributes (renamed):
alignmentwritingDirection"left_to_right"firstLineIndentstartIndentendIndentspaceBeforespaceAfterposition{from, to} — paragraph rangeText object top-level — CHANGED and NEW
contenttextOrientation"horizontal" — moved from per-character-stylemissingFontsantiAliasing"crisp"frametext.type + text.frameType fields (see below)Text frame — CHANGED
Old text frame fields:
{
"type": "area",
"frameType": "inPath"
}
New frame object:
{
"type": "area",
"bounds": { "top": 0, "left": 0, "bottom": 100, "right": 300 },
"boundsRaw": { "left": 0, "top": 0, "right": 300, "bottom": 100 },
"matrix": { "f_xx": 1, "f_xy": 0, "f_yx": 0, "f_yy": 1, "f_tx": 0, "f_ty": 0 },
"baselineAlignment": { "flag": 0, "minimum": 0 }
}
type"area"frameTypeframe objectboundsboundsRawmatrixbaselineAlignment{flag, minimum} baseline alignment parametersSummary: new vs. changed
Fully new fields (absent in V1)
- Document-level metadata:
bounds,imageMode,depth,iccProfile,xmp,title,resolution,globalLightingAngle,globalLightingAltitude,layerFXVisible,pixelScaleFactor protectionarray (replaceslocked)userMask,vectorMaskper-layer;pixelMask(restructured frommask)compositeFrame,referenceFrame,compositeDimensionsper-layer boundsproportionalScaling,effects,layerSettingsblock- Extended
blendOptionsfields:clipped,interior,fillOpacity,knockout,channelRestrictions,blendRanges - Text:
missingFonts,antiAliasing,textOrientation,frame.bounds,frame.boundsRaw,frame.matrix,frame.baselineAlignment - Text warp:
layerSettings.layerSpecific.textLayerSettingsblock - Character style:
fontAlpha,syntheticBold,syntheticItalic,underline,capsOption,lineHeight,letterSpacing,position - Paragraph:
writingDirection,firstLineIndent,startIndent,endIndent,spaceBefore,spaceAfter,position - Smart object:
isSmartObject,isValid,smartObjectData.transform,ccLibrariesElement,extracted - Artboard:
typeAttributes.artboardblock,artboardPresetName,artboardRect, background color,guideIDs - Background layer:
backgroundLayerflag,background.canConvertToLayer(notypeAttributes) - Adjustment
adjustments.typediscriminant; new adjustment types:curves,gradient_map_custom_stops versiontop-level field
Changed fields (present in both, different shape)
- Document field renames:
bitDepth→depth,iccProfileName→iccProfile,name→title,height+width→bounds;photoshopBuildremoved - Layer type names (see Layer type taxonomy)
boundsformat:{height,left,top,width}→{left,top,right,bottom}locked(boolean) →protection(array of strings)rotate→rotation(renamed)mask→pixelMask(restructured;offset.{x,y}→offset.{horizontal,vertical};extendOpaqueandboundsadded)thumbnail: plain string URL →{mediaType, url}object- Artboard children key:
children[]→layers[] - Text
fontrestructured:fontName/fontAvailable→font.postScriptName/font.isAvailable - Text paragraph array:
paragraphStyles→paragraphAttributes - Text frame:
{type, frameType}→frameobject with bounds + matrix - Smart object: flat
{instanceId, linked, name, path, type}→ nested{isLinked, isValid, smartObjectData: {fileInfo, transform}, extracted} - Smart object MIME string
type→fileTypeshort code (e.g."ps3") - Adjustment
adjustmentsblock: per-type keys renamed to snake_case;typediscriminant added;vibrancefields hoisted;exposurevalue renamed toexposureValue;hueSaturation.channels[]→hueSaturationAdjustments[]