> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/api-reference/tenant-configuration/sftp.md).

# Sftp

## List files in a tenant's SFTP inbox

> Returns every file currently visible in the tenant's SFTP inbox, each tagged with its status.\
> Returns an empty list — not an error — when the tenant has no SFTP inbox.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Sftp"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.sftp:read"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"SftpFileResponse":{"required":["blobPath","fileName","lastModified","sizeInBytes","status"],"type":"object","properties":{"fileName":{"type":"string","description":"Original file name (stripped of any internal timestamp prefix)."},"status":{"type":"string","description":"One of `pending`, `processed`, or `error`."},"sizeInBytes":{"type":"integer","description":"File size in bytes.","format":"int64"},"lastModified":{"type":"string","description":"When the file was last written, in UTC.","format":"date-time"},"blobPath":{"type":"string","description":"Stable identifier for this specific file run. Pass this to the import-log endpoint.\nUnlike Neo.Web.Api.Admin.Controllers.Sftp.SftpController.SftpFileResponse.FileName, this is unique even when the same file name is re-imported\nmultiple times: each run produces a distinct blob path."}},"additionalProperties":false,"description":"One file sitting in the tenant's SFTP inbox."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/sftp/files":{"get":{"tags":["Sftp"],"summary":"List files in a tenant's SFTP inbox","description":"Returns every file currently visible in the tenant's SFTP inbox, each tagged with its status.\nReturns an empty list — not an error — when the tenant has no SFTP inbox.","parameters":[{"name":"status","in":"query","description":"Optional filter: `pending`, `processed`, or `error`.","schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File list returned.","content":{"text/plain":{"schema":{"type":"array","items":{"description":"One file sitting in the tenant's SFTP inbox.","$ref":"#/components/schemas/SftpFileResponse"}}},"application/json":{"schema":{"type":"array","items":{"description":"One file sitting in the tenant's SFTP inbox.","$ref":"#/components/schemas/SftpFileResponse"}}},"text/json":{"schema":{"type":"array","items":{"description":"One file sitting in the tenant's SFTP inbox.","$ref":"#/components/schemas/SftpFileResponse"}}}}},"400":{"description":"Invalid status filter.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"401":{"description":"Not authorized.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Download one SFTP-dropped file

> Streams the file exactly as the customer dropped it — no parsing, no reformatting — as an\
> attachment named after the file itself.\
> &#x20;           \
> The body is gzip-compressed on the fly whenever the caller advertises \`Accept-Encoding: gzip\`,\
> which every browser does: these drops are overwhelmingly CSV, where gzip cuts the transfer by\
> roughly an order of magnitude. This is transport compression, not a different artifact — the\
> client decompresses transparently and ends up with the original file, byte for byte, under its\
> original name. A caller that does not advertise gzip gets the bytes uncompressed.\
> &#x20;           \
> \`tenant.sftp:download\` is deliberately separate from \`tenant.sftp:read\`, which\
> exposes file names, row counts and pass identifiers but never the customer data in the file.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Sftp"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.sftp:download"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/sftp/files/content":{"get":{"tags":["Sftp"],"summary":"Download one SFTP-dropped file","description":"Streams the file exactly as the customer dropped it — no parsing, no reformatting — as an\nattachment named after the file itself.\n            \nThe body is gzip-compressed on the fly whenever the caller advertises `Accept-Encoding: gzip`,\nwhich every browser does: these drops are overwhelmingly CSV, where gzip cuts the transfer by\nroughly an order of magnitude. This is transport compression, not a different artifact — the\nclient decompresses transparently and ends up with the original file, byte for byte, under its\noriginal name. A caller that does not advertise gzip gets the bytes uncompressed.\n            \n`tenant.sftp:download` is deliberately separate from `tenant.sftp:read`, which\nexposes file names, row counts and pass identifiers but never the customer data in the file.","parameters":[{"name":"blobPath","in":"query","description":"Blob path, exactly as returned by the `blobPath` field in the files list endpoint.","schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File content returned as an attachment.","content":{"text/plain":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"type":"string","format":"binary"}},"text/json":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Not authorized.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"404":{"description":"No file with this blob path was found in the tenant's SFTP inbox.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Get the import log for one SFTP-dropped file

> Returns the full story of what happened when this file was imported: whether the import\
> function itself ran cleanly, aggregate row counts, and a per-pass breakdown of which customer\
> passes were touched and which failed, with the reason.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Sftp"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.sftp:read"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"SftpImportLogResponse":{"required":["fileRunFound","passOutcomes","status"],"type":"object","properties":{"status":{"type":"string","description":"Current status of the file: `pending`, `processed`, or `error`."},"fileRunFound":{"type":"boolean","description":"Whether a matching import run was found in the log store. false while the file is pending."},"fileRunSuccess":{"type":["null","boolean"],"description":"Whether the import function itself completed successfully. null when not found."},"batchCount":{"type":["null","integer"],"description":"Number of batches sent to the wallet update pipeline.","format":"int32"},"rowCount":{"type":["null","integer"],"description":"Total rows read from the file.","format":"int32"},"successCount":{"type":["null","integer"],"description":"Rows that resolved to at least one pass and were queued for update.","format":"int32"},"noMatchCount":{"type":["null","integer"],"description":"Rows whose identifiers matched no pass at all — a data-quality signal, not a technical failure.","format":"int32"},"errorCount":{"type":["null","integer"],"description":"Rows that threw while being transformed.","format":"int32"},"passOutcomes":{"type":"array","items":{"description":"Outcome of a single pass touched by an imported file.","$ref":"#/components/schemas/SftpPassOutcomeResponse"},"description":"Per-pass breakdown. Empty when none could be recovered — not necessarily an error."}},"additionalProperties":false,"description":"Full story of what happened when one SFTP-dropped file was imported."},"SftpPassOutcomeResponse":{"required":["success"],"type":"object","properties":{"passId":{"type":["null","string"],"description":"Pass identifier, when it could be recovered from the execution's logs."},"success":{"type":"boolean","description":"Whether the push-update for this pass succeeded."},"errorMessage":{"type":["null","string"],"description":"Failure reason, when available. null on success."}},"additionalProperties":false,"description":"Outcome of a single pass touched by an imported file."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/sftp/files/log":{"get":{"tags":["Sftp"],"summary":"Get the import log for one SFTP-dropped file","description":"Returns the full story of what happened when this file was imported: whether the import\nfunction itself ran cleanly, aggregate row counts, and a per-pass breakdown of which customer\npasses were touched and which failed, with the reason.","parameters":[{"name":"blobPath","in":"query","description":"Blob path, exactly as returned by the `blobPath` field in the files list endpoint. Uniquely identifies one file run even when the same file name is re-imported multiple times.","schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Import log returned.","content":{"text/plain":{"schema":{"description":"Full story of what happened when one SFTP-dropped file was imported.","$ref":"#/components/schemas/SftpImportLogResponse"}},"application/json":{"schema":{"description":"Full story of what happened when one SFTP-dropped file was imported.","$ref":"#/components/schemas/SftpImportLogResponse"}},"text/json":{"schema":{"description":"Full story of what happened when one SFTP-dropped file was imported.","$ref":"#/components/schemas/SftpImportLogResponse"}}}},"401":{"description":"Not authorized.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"404":{"description":"No file with this blob path was found in the tenant's SFTP inbox.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Get SFTP status for a tenant

> Reports whether SFTP (Triglav) file import is enabled for the tenant, and a quick activity\
> summary. A tenant with no SFTP inbox simply has the feature disabled — this is the normal\
> case for most tenants, reflected as \`sftpEnabled: false\`, never a 404.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Sftp"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.sftp:read"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"SftpStatusResponse":{"required":["sftpEnabled"],"type":"object","properties":{"sftpEnabled":{"type":"boolean","description":"false when the tenant has no SFTP inbox at all — the normal case for most\n            tenants, not an error. Every other field is null in that case."},"pendingCount":{"type":["null","integer"],"description":"Files dropped but not yet processed.","format":"int32"},"processedCount":{"type":["null","integer"],"description":"Files successfully processed.","format":"int32"},"errorCount":{"type":["null","integer"],"description":"Files that failed processing.","format":"int32"},"lastActivity":{"type":["null","string"],"description":"Timestamp of the most recently modified file across all folders.","format":"date-time"}},"additionalProperties":false,"description":"Quick-glance SFTP activity summary for a tenant."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/admin/sftp/status":{"get":{"tags":["Sftp"],"summary":"Get SFTP status for a tenant","description":"Reports whether SFTP (Triglav) file import is enabled for the tenant, and a quick activity\nsummary. A tenant with no SFTP inbox simply has the feature disabled — this is the normal\ncase for most tenants, reflected as `sftpEnabled: false`, never a 404.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Status returned.","content":{"text/plain":{"schema":{"description":"Quick-glance SFTP activity summary for a tenant.","$ref":"#/components/schemas/SftpStatusResponse"}},"application/json":{"schema":{"description":"Quick-glance SFTP activity summary for a tenant.","$ref":"#/components/schemas/SftpStatusResponse"}},"text/json":{"schema":{"description":"Quick-glance SFTP activity summary for a tenant.","$ref":"#/components/schemas/SftpStatusResponse"}}}},"401":{"description":"Not authorized.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.thewalletcrew.io/api-reference/tenant-configuration/sftp.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
