Two ways in, one handle out, and the two places to name it.
A file arrives in two steps, because those are two different requests: the file
itself is bytes, and what it belongs to is a JSON:API document. So you send the
file first, get a handle back, and name that handle in the thing the file
belongs to.
POST /v1/uploads → handle → imageHandles on a listing attachmentHandles on a message
Until it is named, the file belongs to nobody.
Two ways in
The bytes
An address
multipart/form-data, with a single file part. What every HTTP client on
every platform can send without help, and what an app with a photograph from a
camera has.
An ordinary JSON:API document with a sourceUrl, and we fetch it. For anything
that already hosts its files — a shop, a PIM, a system you are moving away from.
We fetch it while the request is open, so one file is one call. If we cannot
reach it, the answer is 502 with code upload_failed — the same as a storage
service that will not take a file, and for the same reason: nothing you did, and
worth retrying.
The storage service’s own path for the file, and the only name either of us has
for it. This is what you send back.
string
image or video, worked out from the file.
There is no self link and no Location: a pending upload has no address to read
it back at. It is written once, named once, and then it is an attachment.
Naming it
On a listing
imageHandles, up to 8, in the order the gallery should be in.
On a message
attachmentHandles, up to 4.
Nothing after the upload knows which road the file came in by, so a chat
attachment can come from a URL as easily as from a camera: fetch it into a
handle, then name the handle on the message.
What we take
Images and video up to 10 MB: jpg, jpeg, png, gif, webp, heic,
heif, mp4, mov, m4v. Anything else is 422.Scope uploads:write.
A whole gallery is the one case not to use this for. Eight photographs is
eight calls, each waiting on a fetch. Give the listing imageSources instead —
the URLs, all at once — and we fetch the set in the background and skip it
entirely when it has not changed since the last sync. One call, and the second
run costs nothing.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Wristler API","description":"Sync your inventory with Wristler, read back the orders it produces, and build on the rest of the platform.","colors":{"primary":"#1C1C1C","light":"#F0B67F","dark":"#1C1C1C"},"api":{"playground":{"display":"interactive","proxy":false},"examples":{"defaults":"required","languages":["curl","javascript","php","python"],"prefill":true}},"navbar":{"links":[{"href":"mailto:support@wristler.eu","label":"Support"}],"primary":{"type":"button","label":"Wristler","href":"https://wristler.eu"}},"footer":{"socials":{"website":"https://wristler.eu"}},"seo":{"metatags":{"robots":"noindex, nofollow"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"wristler","hasAudioNarration":false,"actualSubdomain":"wristler","customDomains":["docs.wristler.eu"],"gitSource":{"type":"github","owner":"everyday-nl","repo":"wristler.eu","deployBranch":"master","contentDirectory":"resources/api/docs","isPrivate":true,"mountPath":"","label":"","_id":"6aeae85a16290bb1058d617d"},"entitlements":{},"buildId":"6aeae85a16290bb1058d6183","clientVersion":"0.0.4142","searchFilterCounts":[{"language":"default","tag":"API reference","count":137},{"language":"default","tag":"Documentation","count":16},{"language":"default","tag":"Inventory","count":12},{"language":"default","tag":"Account (Security)","count":11},{"language":"default","tag":"Messaging","count":10},{"language":"default","tag":"First Party","count":9},{"language":"default","tag":"Content (Insights)","count":9},{"language":"default","tag":"Content (FAQ)","count":8},{"language":"default","tag":"Orders","count":8},{"language":"default","tag":"How this API works","count":7}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"guides/uploads","slug":"/guides/uploads","pageMetadata":{"title":"Sending us a file","description":"Two ways in, one handle out, and the two places to name it.","href":"/guides/uploads"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Two ways in, one handle out, and the two places to name it.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,..._provideComponents(),...props.components},{Card,CardGroup,CodeBlock,Heading,ResponseField,Tab,Tabs,Warning}=_components;if(!Card)_missingMdxReference(`Card`,true);if(!CardGroup)_missingMdxReference(`CardGroup`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!ResponseField)_missingMdxReference(`ResponseField`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`A file arrives in two steps, because those are two different requests: the file\nitself is bytes, and what it belongs to is a JSON:API document. So you send the\nfile first, get a `,_jsx(_components.strong,{children:`handle`}),` back, and name that handle in the thing the file\nbelongs to.`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`3`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`POST /v1/uploads → handle → imageHandles on a listing`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` attachmentHandles on a message`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(_components.p,{children:`Until it is named, the file belongs to nobody.`}),`\n`,_jsx(Heading,{level:`2`,id:`two-ways-in`,children:`Two ways in`}),`\n`,_jsxs(Tabs,{children:[_jsxs(Tab,{title:`The bytes`,id:`the-bytes`,children:[_jsxs(_components.p,{children:[_jsx(_components.code,{children:`multipart/form-data`}),`, with a single `,_jsx(_components.code,{children:`file`}),` part. What every HTTP client on\nevery platform can send without help, and what an app with a photograph from a\ncamera has.`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -X`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` POST`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` https://api.wristler.eu/v1/uploads`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Authorization: Bearer `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`$TOKEN`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Accept: application/vnd.api+json\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -F`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` file=@front.jpg`})]}),`\n`]})})})]}),_jsxs(Tab,{title:`An address`,id:`an-address`,children:[_jsxs(_components.p,{children:[`An ordinary JSON:API document with a `,_jsx(_components.code,{children:`sourceUrl`}),`, and we fetch it. For anything\nthat already hosts its files — a shop, a PIM, a system you are moving away from.`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -X`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` POST`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` https://api.wristler.eu/v1/uploads`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Authorization: Bearer `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`$TOKEN`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Content-Type: application/vnd.api+json\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -H`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Accept: application/vnd.api+json\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '{\"data\":{\"type\":\"pending-uploads\",\"attributes\":{\"sourceUrl\":\"https://your-shop.example/front.jpg\"}}}'`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`We fetch it while the request is open, so one file is one call. If we cannot\nreach it, the answer is `,_jsx(_components.code,{children:`502`}),` with code `,_jsx(_components.code,{children:`upload_failed`}),` — the same as a storage\nservice that will not take a file, and for the same reason: nothing you did, and\nworth retrying.`]})]})]}),`\n`,_jsx(_components.p,{children:`Both answer the same thing:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`11`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"data\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"pending-uploads\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"8812\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"attributes\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"handle\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"/wristler-image-storage/front-20260923.jpeg\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"fileType\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"image\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"createdAt\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"2026-09-23T09:14:02+00:00\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(ResponseField,{name:`handle`,type:`string`,id:`param-handle`,children:_jsx(_components.p,{children:`The storage service’s own path for the file, and the only name either of us has\nfor it. This is what you send back.`})}),`\n`,_jsx(ResponseField,{name:`fileType`,type:`string`,id:`param-file-type`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`image`}),` or `,_jsx(_components.code,{children:`video`}),`, worked out from the file.`]})}),`\n`,_jsxs(_components.p,{children:[`There is no `,_jsx(_components.code,{children:`self`}),` link and no `,_jsx(_components.code,{children:`Location`}),`: a pending upload has no address to read\nit back at. It is written once, named once, and then it is an attachment.`]}),`\n`,_jsx(Heading,{level:`2`,id:`naming-it`,children:`Naming it`}),`\n`,_jsxs(CardGroup,{cols:2,children:[_jsx(Card,{title:`On a listing`,icon:`camera`,href:`/guides/images`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`imageHandles`}),`, up to 8, in the order the gallery should be in.`]})}),_jsx(Card,{title:`On a message`,icon:`paperclip`,href:`/app/messaging`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`attachmentHandles`}),`, up to 4.`]})})]}),`\n`,_jsx(_components.p,{children:`Nothing after the upload knows which road the file came in by, so a chat\nattachment can come from a URL as easily as from a camera: fetch it into a\nhandle, then name the handle on the message.`}),`\n`,_jsx(Heading,{level:`2`,id:`what-we-take`,children:`What we take`}),`\n`,_jsxs(_components.p,{children:[`Images and video up to `,_jsx(_components.strong,{children:`10 MB`}),`: `,_jsx(_components.code,{children:`jpg`}),`, `,_jsx(_components.code,{children:`jpeg`}),`, `,_jsx(_components.code,{children:`png`}),`, `,_jsx(_components.code,{children:`gif`}),`, `,_jsx(_components.code,{children:`webp`}),`, `,_jsx(_components.code,{children:`heic`}),`,\n`,_jsx(_components.code,{children:`heif`}),`, `,_jsx(_components.code,{children:`mp4`}),`, `,_jsx(_components.code,{children:`mov`}),`, `,_jsx(_components.code,{children:`m4v`}),`. Anything else is `,_jsx(_components.code,{children:`422`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Scope `,_jsx(_components.code,{children:`uploads:write`}),`.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`A whole gallery is the one case not to use this for.`}),` Eight photographs is\neight calls, each waiting on a fetch. Give the listing `,_jsx(_components.code,{children:`imageSources`}),` instead —\nthe URLs, all at once — and we fetch the set in the background and skip it\nentirely when it has not changed since the last sync. One call, and the second\nrun costs nothing.`]})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Sending us a file","description":"Two ways in, one handle out, and the two places to name it.","href":"/guides/uploads"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Two ways in","slug":"two-ways-in","depth":2,"children":[]},{"title":"Naming it","slug":"naming-it","depth":2,"children":[]},{"title":"What we take","slug":"what-we-take","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"wristler","siteName":"Wristler API","title":"Sending us a file - Wristler API","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-15T11:38:22.920Z","originalFileLocation":"guides/uploads.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Two ways in, one handle out, and the two places to name it.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Wristler API\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"noindex, nofollow\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/wristler/_generated/favicon/apple-touch-icon.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/wristler/_generated/favicon/favicon-32x32.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/wristler/_generated/favicon/favicon-16x16.png?v=3\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/wristler/_generated/favicon/favicon.ico?v=3\">\u003cmeta data-mint-head property=\"og:title\" content=\"Sending us a file - Wristler API\">\u003cmeta data-mint-head property=\"og:description\" content=\"Two ways in, one handle out, and the two places to name it.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Wristler API\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.wristler.eu/guides/uploads\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://wristler.mintlify.site/_mintlify/api/og/v2?division=Guides\u0026amp;title=Sending+us+a+file\u0026amp;description=Two+ways+in%2C+one+handle+out%2C+and+the+two+places+to+name+it.\u0026amp;theme=4993fb556950bd5c1d84bdb6\u0026amp;signature=3d2ea9161e7c9ba110c48485b614f674d4e4b64cb53db19241d4461b11f46b23\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Sending us a file - Wristler API\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Two ways in, one handle out, and the two places to name it.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://wristler.mintlify.site/_mintlify/api/og/v2?division=Guides\u0026amp;title=Sending+us+a+file\u0026amp;description=Two+ways+in%2C+one+handle+out%2C+and+the+two+places+to+name+it.\u0026amp;theme=4993fb556950bd5c1d84bdb6\u0026amp;signature=3d2ea9161e7c9ba110c48485b614f674d4e4b64cb53db19241d4461b11f46b23\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/wristler/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Wristler API\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#1C1C1C\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.wristler.eu/guides/uploads\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/guides/uploads.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.wristler.eu/#organization\",\"name\":\"Wristler API\",\"url\":\"https://docs.wristler.eu\"},{\"@type\":\"WebSite\",\"@id\":\"https://docs.wristler.eu#website\",\"name\":\"Wristler API\",\"url\":\"https://docs.wristler.eu\",\"publisher\":{\"@id\":\"https://docs.wristler.eu/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.wristler.eu/guides/uploads#webpage\",\"url\":\"https://docs.wristler.eu/guides/uploads\",\"name\":\"Sending us a file\",\"description\":\"Two ways in, one handle out, and the two places to name it.\",\"dateModified\":\"2026-10-15T11:38:22.920Z\",\"isPartOf\":{\"@id\":\"https://docs.wristler.eu#website\"},\"breadcrumb\":{\"@id\":\"https://docs.wristler.eu/guides/uploads#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.wristler.eu/guides/uploads#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Guides\",\"item\":\"https://docs.wristler.eu/guides/authentication\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Sending us a file\",\"item\":\"https://docs.wristler.eu/guides/uploads\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.wristler.eu/guides/uploads#article\",\"headline\":\"Sending us a file\",\"name\":\"Sending us a file\",\"description\":\"Two ways in, one handle out, and the two places to name it.\",\"url\":\"https://docs.wristler.eu/guides/uploads\",\"mainEntityOfPage\":{\"@id\":\"https://docs.wristler.eu/guides/uploads#webpage\"},\"dateModified\":\"2026-10-15T11:38:22.920Z\",\"publisher\":{\"@id\":\"https://docs.wristler.eu/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.wristler.eu#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Wristler API\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Wristler API\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/guides/uploads.md","siteName":"Wristler API","nav":{"global":null,"tabs":[{"tab":"Documentation","groups":[{"group":"Get started","pages":[{"title":"Wristler API","href":""},{"title":"Quickstart","href":"/quickstart"}]},{"group":"How this API works","pages":[{"title":"JSON:API in practice","href":"/concepts/json-api"},{"title":"Scopes","href":"/concepts/scopes"},{"title":"Pagination","href":"/concepts/pagination"},{"title":"Rate limits","href":"/concepts/rate-limits"},{"title":"Retrying safely","href":"/concepts/idempotency"},{"title":"Errors","href":"/concepts/errors"},{"title":"Listings a Connect feed maintains","href":"/concepts/feed-ownership"}]},{"group":"Guides","pages":[{"title":"Authentication","href":"/guides/authentication"},{"title":"Syncing an inventory","href":"/guides/inventory"},{"title":"Photographs","description":"Two roads to a gallery: URLs we fetch, or files you upload.","href":"/guides/images"},{"title":"Sending us a file","href":"/guides/uploads"},{"title":"Orders","description":"Pulling what a seller has to fulfil, and recording that it shipped.","href":"/guides/orders"},{"title":"A seller's own settings","href":"/guides/business"}]},{"group":"Partners","pages":[{"title":"What a third-party integration can do","href":"/partners/capabilities"}]}]},{"tab":"First Party","pages":[{"title":"First Party","href":"/app"}]},{"tab":"API reference","pages":[{"title":"API reference","href":"/api-reference/authentication/show-current-user"}]}]},"basePath":"","title":"Sending us a file - Wristler API","buildId":"dpl_G2Qd45vZZ7MkBiGF9yYx8ZsbbKXX","deploymentId":"dpl_G2Qd45vZZ7MkBiGF9yYx8ZsbbKXX","dynamics":[],"chunks":[]}