Enterprise S3 File Intake Workflow
All templates

Enterprise S3 File Intake Workflow

Govern files stored in AWS S3 without Xano ever holding the bytes. Register uploaded objects, validate file type and size, route through an approval state machine, and maintain a full audit trail — all joined to S3 by object key.

Start building in Xano: Access the prompt at https://go.xano.co/start-xano-with-template-skill and run it here with file-intake-s3 as your template.
ClaudeOpenAI CodexCursorVS Code

Copy and paste the prompt in your local coding agent of choice.

Template Details

4 Tables 8 APIs 7 Functions

Integrations

AWS S3
Template Preview
Client appClient appWeb · mobile · agents3_file_intake APIs3_file_intake APIfiles/{file_id}/approvefiles/{file_id}/mark-processedfiles/registerfiles/{file_id}/rejectfiles/{file_id}/send-to-reviewfiles/{file_id}/statusfiles/{file_id}/validateBusiness logicBusiness logicS3 file intake check authS3 file intake check transitionS3 file intake log requestS3 file intake record eventS3 file intake s3 headS3 file intake s3 object urlS3 file intake validate meta...DataDataapi_request_logsfile_eventsfile_reviewsfilesExternal servicesExternal services AWS S3

Overview

Govern files stored in AWS S3 without Xano ever holding the bytes — register uploaded objects, validate type and size, route them through an approval state machine, and keep a full audit trail, all joined to S3 by object key.

S3 is the system of record for the bytes; Xano is the system of record for the metadata, status, and decisions. Drop this into a Xano workspace, point it at your bucket, and you get a complete intake pipeline — register → validate → review → approve → process — with every step guarded and logged.

What it provides

Files arrive in a bucket and then what? Someone eyeballs them, moves the good ones somewhere, and the record of "who approved this, when, and why" lives in memory or a thread. There's no gate that stops an unvalidated or unapproved file from moving downstream, and no reconstructable history when finance or audit asks.

This template makes the intake a governed workflow instead of a convention. Every file moves through an explicit state machine — registered → validated → needs_review → approved → processed (with failed and rejected branches) — and illegal transitions are refused server-side, not left to the UI. Validation runs at the gate (allowed type, size ceiling, and an optional real S3 object-existence check). Every transition appends an immutable event, every review is recorded, and every API call is logged on success and failure. Xano owns the workflow and the audit; S3 keeps holding the bytes.

Repo layout

backend/
  api/
    s3_file_intake/
      api_group.xs
      files_approve_post.xs
      files_mark_processed_post.xs
      files_register_post.xs
      files_reject_post.xs
      files_send_to_review_post.xs
      files_status_get.xs
      files_validate_post.xs
  function/
    s3_file_intake_check_auth.xs
    s3_file_intake_check_transition.xs
    s3_file_intake_log_request.xs
    s3_file_intake_record_event.xs
    s3_file_intake_s3_head.xs
    s3_file_intake_s3_object_url.xs
    s3_file_intake_validate_metadata.xs
  table/
    api_request_logs.xs
    file_events.xs
    file_reviews.xs
    files.xs
  workflow_test/
    s3_file_intake_happy_path.xs
    s3_file_intake_reject_path.xs
  workspace/
    templates.xs

How it works

A file is a row in files carrying a status and joined to its S3 object by a unique s3_key. The lifecycle is a guarded state machine — the transition guard (s3_file_intake_check_transition) is a pure function, so the rules hold no matter which endpoint is called:

                ┌──────────────► failed        (bad type/size, or S3 object missing)
                │
 registered ──► validated ──► needs_review ──► approved ──► processed
                                    │
                                    └────────► rejected
  • register records the metadata and creates the files row (registered).
  • validate (only from registered) checks the type is one of pdf | csv | xlsx | json and size ≤ 25 MB; if AWS credentials are set it additionally confirms the object exists in S3 via Xano's native cloud.aws.s3.get_file_info. Passes → validated, fails → failed.
  • send-to-review (only from validated) opens a pending review → needs_review.
  • approve / reject (only from needs_review) record a reviewer decision.
  • mark-processed (only from approved) closes the loop → processed.

Every transition appends a file_events row, so a file's history is always reconstructable from the log; every request writes an api_request_logs row. There is deliberately no AI extraction and no Azure/GCS support — this is intake, validation, approval, and auditability.

Quick start

Start with your coding agent. Paste the prompt below into a local MCP-capable coding agent — Claude Code, Cursor, Windsurf, and others. It installs the Xano CLI, connects Xano, and imports this template.

Start building in Xano: Access the prompt at https://go.xano.co/start-xano-with-template-skill and run it here with file-intake-s3 as your template.

The agent will walk you through the setup below.

  1. Push the backend to a Xano workspace (the CLI/agent flow below does this).
  2. Call the flowPOST /files/registerPOST /files/{file_id}/validatesend-to-reviewapprovemark-processed, then GET /files/{file_id}/status for the metadata + full event history.
  3. It runs before you wire S3. With API_AUTH_SECRET unset the auth check is a deliberate no-op, and with the AWS keys unset the S3 object-existence check is skipped (validation still runs on the declared metadata) — so the whole state machine works out of the box. Set the environment variables to enforce auth and confirm objects really exist in your bucket.

API surface

All endpoints live in the S3FileIntake API group (canonical s3-file-intake) and require the API secret when API_AUTH_SECRET is set (header X-API-Secret: <secret> or an api_secret field). Every call writes an api_request_logs row.

Method Path Purpose
POST /files/register Record an uploaded object's metadata → a registered files row + event.
POST /files/{file_id}/validate Validate type + size (and S3 existence when creds are set) → validated or failed.
POST /files/{file_id}/send-to-review From validatedneeds_review + a pending review row.
POST /files/{file_id}/approve From needs_reviewapproved (records reviewer + note).
POST /files/{file_id}/reject From needs_reviewrejected (requires a note).
POST /files/{file_id}/mark-processed From approvedprocessed.
GET /files/{file_id}/status Metadata, current status, latest review, canonical S3 URL, and full event history.

Database Tables

  • files — one row per file: s3_key (unique), file_name, file_type, file_size_bytes, uploaded_by, status, timestamps.
  • file_events — append-only audit trail: one row per lifecycle action (file_id, event_type, event_payload, created_by).
  • file_reviews — one row per review: review_status (pendingapproved / rejected), reviewer_id, review_note.
  • api_request_logs — one row per API call (endpoint, requester, status, error), written on success and failure.

Testing

Run from a deployed workspace with xano workflow_test run_all:

  • s3_file_intake_happy_path — register → validate → send-to-review → approve → mark-processed, asserting each status transition and the resulting event trail.
  • s3_file_intake_reject_path — the review-rejection branch and that illegal transitions are refused.

Both run credential-free (the S3 existence check is skipped and the auth check is a no-op when their env vars are unset), so the full state machine is exercised without an AWS account.

Environment variables

Set these in your Xano workspace (Settings → Environment Variables) to enforce auth and enable the real S3 checks. The state machine runs without them (auth no-op, S3 existence check skipped).

  • S3_BUCKET_NAME — your bucket; used to build the canonical S3 object URL and for the existence check.
  • AWS_REGION — the bucket's region; used for the URL and the existence check.
  • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY — used by validate to confirm the object exists in S3 (cloud.aws.s3.get_file_info). When unset, the existence check is skipped and validation runs on the declared metadata only.
  • API_AUTH_SECRET — the shared secret every endpoint checks (via X-API-Secret header or api_secret field). When unset the check is a deliberate no-op so the module runs out of the box; set it in production.

Frequently asked questions

What file types and sizes does it accept?
It accepts pdf, csv, xlsx, and json up to 25 MB; anything else is marked `failed` at validation. The allowed types and size ceiling live in one validation function (`s3_file_intake_validate_metadata`), so you widen or narrow them in one place.
No — S3 holds the bytes; Xano only stores each file's metadata, status, and decision history, joined to the object by its `s3_key`. When AWS credentials are set, the validate step confirms the object actually exists in S3 via Xano's native `cloud.aws.s3.get_file_info`.
The workflow keys off object metadata (bucket and key), so the register → validate → approve flow isn't tied to AWS. The optional object-existence check goes through Xano's native AWS S3 connector, so for a fully S3-compatible store you'd point that at your endpoint and confirm compatibility.
Every template runs on any Xano plan, including the free tier. All you need is a Xano account and a coding agent connected to the CLI and Developer MCP.
You can import and run it with your local coding agent — it works against the seed data it ships with. Paste this prompt into your agent: Start building in Xano: Access the prompt at https://go.xano.co/start-xano-with-template-skill and run it here with file-intake-s3 as your template. You can also do a manual clone from Github, still using the Xano CLI and Developer MCP to connect to Xano to build and deploy.
Yes — that's the intent. The backend is plain XanoScript that you can read and AI can build on: add or edit tables, endpoints, and logic, or swap integrations. It ships with tests you can extend as you go.
Xano gives you an enterprise-grade backend — database, APIs, and logic — that AI can build and you can visually inspect, edit, and trust. Hosted, scalable, and production-ready from day one. Speed of generation, without the black box.

Get started for free today

Xano gives you everything you need to ship modern applications—fast, securely, and at scale.

Get started