Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.
mc.storage is a thin wrapper around your private S3 storage area with two
well-known directories:
Incoming/ — files you send in.
Outgoing/ — files placed for you to read.
upload* defaults to Incoming/; download*, list*, and delete default
to Outgoing/ so the natural list-then-act loop targets the same direction.
Override per call with direction="incoming" / direction="outgoing".
pip install "minerva-sdk[storage]"
from minerva import Minervamc = Minerva() # MINERVA_API_KEY from env
Bulk methods run uploads/downloads in parallel — defaults to 8 workers,
tune with max_concurrency=. Order is preserved; the first error in a
batch fails the call.
# Many files at oncemc.storage.upload_many(["a.csv", "b.csv", "c.csv"])# Whole directory tree, relative paths preservedmc.storage.upload_directory("./batch-2026-06-29")# Sends ./batch-2026-06-29/x.csv → Incoming/x.csv# Sends ./batch-2026-06-29/sub/y.csv → Incoming/sub/y.csvmc.storage.upload_directory("./day", subdir="2026-06-29")# → Incoming/2026-06-29/...# Pull a batch by keys (typically the output of list())mc.storage.download_many( ["results-1.csv", "sub/inner.csv"], local_dir="./out",)# List, then download everything — single callmc.storage.download_all(local_dir="./out")
Storage credentials are fetched lazily on first call and cached on the
client. The SDK auto-refreshes them when they’re within ~2 minutes of
expiry, so a long-running process can hold one Minerva() instance and
keep working across hour-long sessions without manual renewal.Construct one Minerva() per process and reuse it — every fresh
instance pays the credential round-trip again.
creds = mc.storage.get_credentials()print(creds.bucket_name, creds.prefix, creds.aws_session_expiration)# Secrets (aws_secret_access_key, aws_session_token) are hidden from repr# but accessible by attribute.
Storage credentials are scoped to your org’s directory — the underlying
session policy only permits s3:GetObject / s3:PutObject /
s3:DeleteObject on {your_org}/* keys, and s3:ListBucket filtered to
the same prefix. Other orgs’ data is unreachable regardless of what you
pass to the SDK.The SDK additionally rejects path-traversal-shaped keys
(.. segments, absolute paths, backslashes) at the call site for clean
local errors — but the real isolation is server-side.
All storage errors derive from MinervaStorageError:
Condition
Raises
[storage] extra not installed (boto3 missing)
MinervaStorageExtraNotInstalledError
Credentials endpoint returned an unexpected shape, missing fields, or unparsable expiry
MinervaStorageCredentialError
Object doesn’t exist (404)
MinervaStorageObjectNotFoundError — carries .key
Access denied (403)
MinervaStorageAccessDeniedError — carries .key
Network / transient S3 failure (5xx, timeouts, …)
MinervaStorageTransferError — carries .original
Bad input (non-file path, .. in key, invalid direction, …)
MinervaValidationError
from minerva import ( MinervaStorageError, MinervaStorageObjectNotFoundError, MinervaStorageAccessDeniedError, MinervaStorageTransferError,)try: mc.storage.download("missing.csv")except MinervaStorageObjectNotFoundError as e: print(f"no such key: {e.key}")except MinervaStorageError: raise
The [storage] extra pulls in boto3 so the base wheel stays small. If
you already have boto3 in your environment, the extra still wires up
the SDK’s lazy-import guard cleanly — install it either way.
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Minerva Documentation","colors":{"primary":"#5B84E7","light":"#8EA8F0","dark":"#2E5BCF"},"logo":{"light":"https://mintcdn.com/minerva-a2a15a3a/4LFBmther9gqOLci/logo/Logo+Wordmark.svg?fit=max\u0026auto=format\u0026n=4LFBmther9gqOLci\u0026q=85\u0026s=80dfff22f85e3503c13e452578128b42","dark":"https://mintcdn.com/minerva-a2a15a3a/4LFBmther9gqOLci/logo/Logo+Wordmark_White.svg?fit=max\u0026auto=format\u0026n=4LFBmther9gqOLci\u0026q=85\u0026s=a312b4352c94561aaf43d34d331bb324"},"favicon":"https://mintcdn.com/minerva-a2a15a3a/taSOw2M7XeR05kge/favicon.svg?fit=max\u0026auto=format\u0026n=taSOw2M7XeR05kge\u0026q=85\u0026s=a062b886b18b17632a5788847a537418","api":{"playground":{"display":"simple"},"mdx":{"auth":{"method":"key","name":"x-api-key"},"server":"https://api.minerva.io"}},"fonts":{"heading":{"family":"ES Schwarzweiss","weight":700,"source":"fonts/ESSchwarzweiss-Variable.woff2","format":"woff2"},"body":{"family":"ES Schwarzweiss","weight":400,"source":"fonts/ESSchwarzweiss-Variable.woff2","format":"woff2"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"minerva-a2a15a3a","hasAudioNarration":false,"actualSubdomain":"minerva-a2a15a3a","customDomains":["docs.minerva.io"],"gitSource":{"type":"github","owner":"minervadata-hq","repo":"md-core","deployBranch":"prod","contentDirectory":"docs/api_sdk/mintlify","isPrivate":true,"mountPath":"","label":""},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"}},"buildId":"6aecd8a42ce0e78217a380cc","clientVersion":"0.0.4117","searchFilterCounts":[{"language":"default","tag":"API Reference","count":29},{"language":"default","tag":"SDK","count":24},{"language":"default","tag":"Person Search","count":11},{"language":"default","tag":"Power features","count":11},{"language":"default","tag":"Endpoints","count":7},{"language":"default","tag":"Core Endpoints","count":6},{"language":"default","tag":"Segments","count":5},{"language":"default","tag":"Getting started","count":5},{"language":"default","tag":"Async Person Search","count":4},{"language":"default","tag":"MCP","count":4}]},"assistantConfig":{"enableAskAiButton":true,"enableStarterQuestions":true,"enableContextualStarterQuestions":true,"enableAskAiSearchBar":false},"basePath":"","hasChatPermissions":true,"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":"llms-txt-v2","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}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"sdk/guides/storage","slug":"/sdk/guides/storage","pageMetadata":{"title":"Storage — bulk upload \u0026 download","description":"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.","href":"/sdk/guides/storage"},"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: \"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.\"\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`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Tip}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[_jsx(_components.code,{children:`mc.storage`}),` is a thin wrapper around your private S3 storage area with two\nwell-known directories:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`Incoming/`}),` — files `,_jsx(_components.strong,{children:`you send`}),` in.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`Outgoing/`}),` — files `,_jsx(_components.strong,{children:`placed for you`}),` to read.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`upload*`}),` defaults to `,_jsx(_components.code,{children:`Incoming/`}),`; `,_jsx(_components.code,{children:`download*`}),`, `,_jsx(_components.code,{children:`list*`}),`, and `,_jsx(_components.code,{children:`delete`}),` default\nto `,_jsx(_components.code,{children:`Outgoing/`}),` so the natural list-then-act loop targets the same direction.\nOverride per call with `,_jsx(_components.code,{children:`direction=\"incoming\"`}),` / `,_jsx(_components.code,{children:`direction=\"outgoing\"`}),`.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,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:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`pip`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"minerva-sdk[storage]\"`})]}),`\n`]})})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`python`,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:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` minerva `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Minerva`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Minerva() `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# MINERVA_API_KEY from env`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`single-file`,children:`Single file`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`20`,language:`python`,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:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`20`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Upload — defaults to Incoming/`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.upload(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"data/customers.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# → Incoming/customers.csv`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.upload(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"data/customers.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`remote_name`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"batch-001.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# → Incoming/batch-001.csv`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.upload(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"data/customers.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`subdir`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"2026-06-29\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# → Incoming/2026-06-29/customers.csv`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Download — defaults to Outgoing/`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.download(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"results.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# → ./results.csv`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.download(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sub/inner.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`local_path`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"out/inner.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# → ./out/inner.csv (creates parent dirs)`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Delete — defaults to Outgoing/. Pass direction=\"incoming\" to clean up your own uploads.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.delete(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"results.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.delete(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"batch-001.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`direction`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"incoming\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`upload`}),` returns the relative remote key. `,_jsx(_components.code,{children:`download`}),` returns the local\n`,_jsx(_components.code,{children:`Path`}),` that was written.`]}),`\n`,_jsx(Heading,{level:`2`,id:`listing`,children:`Listing`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`python`,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:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` obj `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` mc.storage.list(): `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Outgoing/ by default`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(obj.key, obj.size, obj.last_modified)`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` obj `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` mc.storage.list(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`subdir`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"2026-06\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` ...`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Each `,_jsx(_components.code,{children:`ObjectMeta`}),` carries `,_jsx(_components.code,{children:`key`}),` (relative — pass back to `,_jsx(_components.code,{children:`download`}),` /\n`,_jsx(_components.code,{children:`delete`}),` as-is), `,_jsx(_components.code,{children:`size`}),`, `,_jsx(_components.code,{children:`last_modified`}),`, and `,_jsx(_components.code,{children:`etag`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`bulk`,children:`Bulk`}),`\n`,_jsxs(_components.p,{children:[`Bulk methods run uploads/downloads in parallel — defaults to 8 workers,\ntune with `,_jsx(_components.code,{children:`max_concurrency=`}),`. Order is preserved; the first error in a\nbatch fails the call.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`19`,language:`python`,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:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`19`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Many files at once`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.upload_many([`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"a.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"b.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"c.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`])`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Whole directory tree, relative paths preserved`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.upload_directory(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"./batch-2026-06-29\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Sends ./batch-2026-06-29/x.csv → Incoming/x.csv`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Sends ./batch-2026-06-29/sub/y.csv → Incoming/sub/y.csv`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.upload_directory(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"./day\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`subdir`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"2026-06-29\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# → Incoming/2026-06-29/...`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Pull a batch by keys (typically the output of list())`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.download_many(`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"results-1.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sub/inner.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`],`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` local_dir`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"./out\"`}),_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`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# List, then download everything — single call`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`mc.storage.download_all(`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`local_dir`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"./out\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`credentials`,children:`Credentials`}),`\n`,_jsxs(_components.p,{children:[`Storage credentials are fetched lazily on first call and cached on the\nclient. The SDK auto-refreshes them when they’re within ~2 minutes of\nexpiry, so a long-running process can hold one `,_jsx(_components.code,{children:`Minerva()`}),` instance and\nkeep working across hour-long sessions without manual renewal.`]}),`\n`,_jsxs(_components.p,{children:[`Construct `,_jsxs(_components.strong,{children:[`one `,_jsx(_components.code,{children:`Minerva()`}),` per process and reuse it`]}),` — every fresh\ninstance pays the credential round-trip again.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`python`,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:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`creds `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` mc.storage.get_credentials()`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(creds.bucket_name, creds.prefix, creds.aws_session_expiration)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Secrets (aws_secret_access_key, aws_session_token) are hidden from repr`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# but accessible by attribute.`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`access-scope`,children:`Access scope`}),`\n`,_jsxs(_components.p,{children:[`Storage credentials are scoped to your org’s directory — the underlying\nsession policy only permits `,_jsx(_components.code,{children:`s3:GetObject`}),` / `,_jsx(_components.code,{children:`s3:PutObject`}),` /\n`,_jsx(_components.code,{children:`s3:DeleteObject`}),` on `,_jsx(_components.code,{children:`{your_org}/*`}),` keys, and `,_jsx(_components.code,{children:`s3:ListBucket`}),` filtered to\nthe same prefix. Other orgs’ data is unreachable regardless of what you\npass to the SDK.`]}),`\n`,_jsxs(_components.p,{children:[`The SDK additionally rejects path-traversal-shaped keys\n(`,_jsx(_components.code,{children:`..`}),` segments, absolute paths, backslashes) at the call site for clean\nlocal errors — but the real isolation is server-side.`]}),`\n`,_jsx(Heading,{level:`2`,id:`errors`,children:`Errors`}),`\n`,_jsxs(_components.p,{children:[`All storage errors derive from `,_jsx(_components.code,{children:`MinervaStorageError`}),`:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Condition`}),_jsx(_components.th,{children:`Raises`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`[storage]`}),` extra not installed (`,_jsx(_components.code,{children:`boto3`}),` missing)`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`MinervaStorageExtraNotInstalledError`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Credentials endpoint returned an unexpected shape, missing fields, or unparsable expiry`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`MinervaStorageCredentialError`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Object doesn’t exist (404)`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`MinervaStorageObjectNotFoundError`}),` — carries `,_jsx(_components.code,{children:`.key`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Access denied (403)`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`MinervaStorageAccessDeniedError`}),` — carries `,_jsx(_components.code,{children:`.key`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Network / transient S3 failure (5xx, timeouts, …)`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`MinervaStorageTransferError`}),` — carries `,_jsx(_components.code,{children:`.original`})]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[`Bad input (non-file path, `,_jsx(_components.code,{children:`..`}),` in key, invalid `,_jsx(_components.code,{children:`direction`}),`, …)`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`MinervaValidationError`})})]})]})]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`13`,language:`python`,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:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`13`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`from`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` minerva `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_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:` MinervaStorageError,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` MinervaStorageObjectNotFoundError,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` MinervaStorageAccessDeniedError,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` MinervaStorageTransferError,`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`try`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` mc.storage.download(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"missing.csv\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`except`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` MinervaStorageObjectNotFoundError `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` e:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`f`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"no such key: `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`{`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`e.key`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`}`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`except`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` MinervaStorageError:`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` raise`})}),`\n`]})})}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`[storage]`}),` extra pulls in `,_jsx(_components.code,{children:`boto3`}),` so the base wheel stays small. If\nyou already have `,_jsx(_components.code,{children:`boto3`}),` in your environment, the extra still wires up\nthe SDK’s lazy-import guard cleanly — install it either way.`]})})]})}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":"Storage — bulk upload \u0026 download","description":"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.","href":"/sdk/guides/storage"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Single file","slug":"single-file","depth":2,"children":[]},{"title":"Listing","slug":"listing","depth":2,"children":[]},{"title":"Bulk","slug":"bulk","depth":2,"children":[]},{"title":"Credentials","slug":"credentials","depth":2,"children":[]},{"title":"Access scope","slug":"access-scope","depth":2,"children":[]},{"title":"Errors","slug":"errors","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"minerva-a2a15a3a","siteName":"Minerva Documentation","title":"Storage — bulk upload \u0026 download - Minerva Documentation","contextualStarterQuestions":[{"_id":"6a42dfbfff816b35c5314a26","deploymentId":"68ed07362d3e4d2fb94452da","questionText":"How do I download multiple files?","status":"active","generatedBy":"contextual","path":"sdk/guides/storage","createdAt":"2026-06-29T21:12:31.335Z","updatedAt":"2026-06-29T21:12:31.335Z","__v":0},{"_id":"6a42dfbfff816b35c5314a25","deploymentId":"68ed07362d3e4d2fb94452da","questionText":"How do I upload files?","status":"active","generatedBy":"contextual","path":"sdk/guides/storage","createdAt":"2026-06-29T21:12:31.335Z","updatedAt":"2026-06-29T21:12:31.335Z","__v":0}],"navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-06-29T21:12:22.258Z","originalFileLocation":"sdk/guides/storage.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=\"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Minerva Documentation\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Storage — bulk upload \u0026amp; download - Minerva Documentation\">\u003cmeta data-mint-head property=\"og:description\" content=\"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Minerva Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.minerva.io/sdk/guides/storage\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://minerva-a2a15a3a.mintlify.site/_mintlify/api/og/v2?division=Power+features\u0026amp;title=Storage+%E2%80%94+bulk+upload+%26+download\u0026amp;description=Move+files+in+and+out+of+your+private+storage+area+without+writing+boto3+by+hand.+Gated+on+the+%5Bstorage%5D+extra.\u0026amp;theme=e97f3b1d1117a7b9cb640af6\u0026amp;signature=ebd6f0eaa70f9b8261bf063074c1b2433a14f03ee0834f8af89a491b84d2db7d\">\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=\"Storage — bulk upload \u0026amp; download - Minerva Documentation\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://minerva-a2a15a3a.mintlify.site/_mintlify/api/og/v2?division=Power+features\u0026amp;title=Storage+%E2%80%94+bulk+upload+%26+download\u0026amp;description=Move+files+in+and+out+of+your+private+storage+area+without+writing+boto3+by+hand.+Gated+on+the+%5Bstorage%5D+extra.\u0026amp;theme=e97f3b1d1117a7b9cb640af6\u0026amp;signature=ebd6f0eaa70f9b8261bf063074c1b2433a14f03ee0834f8af89a491b84d2db7d\">\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=\"/mintlify-assets/_mintlify/favicons/minerva-a2a15a3a/friUgrjnS8NK6ZsS/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Minerva Documentation\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#5B84E7\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.minerva.io/sdk/guides/storage\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/sdk/guides/storage.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.minerva.io/#organization\",\"name\":\"Minerva Documentation\",\"url\":\"https://docs.minerva.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/minerva-a2a15a3a/4LFBmther9gqOLci/logo/Logo+Wordmark.svg?fit=max\u0026auto=format\u0026n=4LFBmther9gqOLci\u0026q=85\u0026s=80dfff22f85e3503c13e452578128b42\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.minerva.io#website\",\"name\":\"Minerva Documentation\",\"url\":\"https://docs.minerva.io\",\"publisher\":{\"@id\":\"https://docs.minerva.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.minerva.io/sdk/guides/storage#webpage\",\"url\":\"https://docs.minerva.io/sdk/guides/storage\",\"name\":\"Storage — bulk upload \u0026 download\",\"description\":\"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.\",\"dateModified\":\"2026-06-29T21:12:22.258Z\",\"isPartOf\":{\"@id\":\"https://docs.minerva.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.minerva.io/sdk/guides/storage#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.minerva.io/sdk/guides/storage#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Power features\",\"item\":\"https://docs.minerva.io/sdk/guides/async-and-batching\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Storage — bulk upload \u0026 download\",\"item\":\"https://docs.minerva.io/sdk/guides/storage\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.minerva.io/sdk/guides/storage#article\",\"headline\":\"Storage — bulk upload \u0026 download\",\"name\":\"Storage — bulk upload \u0026 download\",\"description\":\"Move files in and out of your private storage area without writing boto3 by hand. Gated on the [storage] extra.\",\"url\":\"https://docs.minerva.io/sdk/guides/storage\",\"mainEntityOfPage\":{\"@id\":\"https://docs.minerva.io/sdk/guides/storage#webpage\"},\"dateModified\":\"2026-06-29T21:12:22.258Z\",\"publisher\":{\"@id\":\"https://docs.minerva.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.minerva.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Minerva Documentation\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Minerva Documentation\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/sdk/guides/storage.md","siteName":"Minerva Documentation","nav":{"global":null,"tabs":[{"tab":"API Reference","pages":[{"title":"API Reference","href":"/api-reference/introduction"}]},{"tab":"MCP","pages":[{"title":"MCP","href":"/minerva-data-mcp"}]},{"tab":"SDK","groups":[{"group":"Getting started","pages":[{"title":"Minerva Python SDK","href":"/sdk/introduction"},{"title":"Installation","href":"/sdk/installation"},{"title":"Quickstart","href":"/sdk/quickstart"},{"title":"Authentication","href":"/sdk/authentication"}]},{"group":"Endpoints","pages":[{"title":"Resolve","href":"/sdk/guides/resolve"},{"title":"Enrich","href":"/sdk/guides/enrich"},{"title":"Person Search","href":"/sdk/guides/person-search"},{"title":"LinkedIn contact info","href":"/sdk/guides/linkedin"},{"title":"Email validation","href":"/sdk/guides/validate-emails"},{"title":"Country inference","href":"/sdk/guides/infer-country"},{"title":"Usage tallies","href":"/sdk/guides/usage"}]},{"group":"Power features","pages":[{"title":"Async + bulk batching","href":"/sdk/guides/async-and-batching"},{"title":"Streaming batcher","href":"/sdk/guides/streaming-batcher"},{"title":"Workflows — `mc.workflows.*`","href":"/sdk/guides/workflows"},{"title":"Rate limiting (built in)","href":"/sdk/guides/rate-limiting"},{"title":"Custom \u0026 tailored endpoints","href":"/sdk/guides/custom-endpoints"},{"title":"Validation \u0026 dry_run","href":"/sdk/guides/validation-dry-run"},{"title":"Output formats","href":"/sdk/guides/output-formats"},{"title":"Spreadsheets — Google Sheets \u0026 Excel","description":"Run resolve / enrich directly off a Google Sheet or .xlsx workbook, and write results back the same way.","href":"/sdk/guides/spreadsheets"},{"title":"Storage — bulk upload \u0026 download","href":"/sdk/guides/storage"},{"title":"Error handling","description":"One exception hierarchy. Specific subclasses where you'd actually want to branch on the failure.","href":"/sdk/guides/error-handling"},{"title":"Liveness","href":"/sdk/guides/health"}]},{"group":"Reference","pages":[{"title":"CLI reference","href":"/sdk/reference/cli"},{"title":"Exception reference","href":"/sdk/reference/errors"}]}]},{"tab":"SFTP","pages":[{"title":"SFTP","href":"/sftp/introduction"}]}]},"basePath":"","title":"Storage — bulk upload \u0026 download - Minerva Documentation","buildId":"dpl_41S5Z2jG9QnfDRwN1KZrLdBwj7DM","deploymentId":"dpl_41S5Z2jG9QnfDRwN1KZrLdBwj7DM","dynamics":[],"chunks":[]}