AI News Hub Logo

AI News Hub

Building Multi-Tenant Document Pipelines: Architecture Guide for Agencies

DEV Community
Iteration Layer

The Five-Client Problem You run an agency. You have five active client projects, each with a document processing pipeline. Client A processes supplier invoices for a fleet management company. Client B extracts data from insurance claims. Client C generates branded PDF reports for a real estate platform. Client D transforms product images for an e-commerce marketplace. Client E does all of the above for a logistics company. Each pipeline is different. Each client has different volume, different budgets, and different compliance requirements. But every pipeline uses the same categories of operations: extract, transform, generate. The operational question is: how do you structure this so it scales to ten clients, then twenty, without the management overhead growing linearly with every new engagement? Most agencies solve this one of two ways, and both are wrong. Approach 1: One shared API key for everything. Fast to set up, impossible to track. When the invoice arrives, you cannot tell how much of the usage came from Client A versus Client C. You cannot set spending limits per client. If one client's pipeline has a bug that burns through credits, every client is affected. And if you need to revoke access for one client (because the engagement ended or the key was compromised), you have to rotate the key for everyone. Approach 2: Separate vendor accounts per client. Clean isolation, but management overhead scales linearly. Five accounts means five logins, five invoices, five credential sets, five separate credit pools. You cannot move unused credits from a quiet client to a busy one. Onboarding a new client means creating a new vendor account, configuring billing, setting up credentials, and adding another line to your monthly reconciliation spreadsheet. There is a better architecture. This guide covers how to structure a multi-tenant document processing setup from a single organization account, with scoped isolation between projects and unified management overhead. Iteration Layer's project system is built for exactly this use case. One organization account, multiple projects. Each project represents a client engagement. Each project has its own scoped API keys, its own usage tracking, and its own optional budget cap. All projects share the organization's credit pool. Organization Account (your agency) ├── Project: Client A (Fleet Management) │ ├── API Key: il_proj_clienta_prod_... │ ├── API Key: il_proj_clienta_dev_... │ ├── Budget Cap: 2,000 credits/month │ └── Usage: tracked separately ├── Project: Client B (Insurance Claims) │ ├── API Key: il_proj_clientb_prod_... │ ├── Budget Cap: 5,000 credits/month │ └── Usage: tracked separately ├── Project: Client C (Real Estate Reports) │ ├── API Key: il_proj_clientc_prod_... │ ├── Budget Cap: 1,000 credits/month │ └── Usage: tracked separately └── Shared Credit Pool: Organization subscription This gives you the isolation of separate accounts with the operational simplicity of one account. Each project gets its own API keys. These keys are scoped to the project — they can only be used to make API calls that are tracked against that project's usage. They cannot see or affect other projects. Security isolation. If a client project's key is compromised (leaked in a git commit, exposed in a client's frontend code, discovered in a log file), you revoke that one key. Other projects are unaffected. No organization-wide key rotation, no downtime for other clients. Usage attribution. Every API call made with a project-scoped key is automatically attributed to that project. When you check usage at the end of the month, you see exactly how many credits each project consumed, broken down by API. No manual tagging, no query parameters to track project IDs, no post-hoc log analysis. Access control. You can give a client's development team a key scoped to their project. They can integrate and test against the API without seeing your other clients' usage, keys, or configuration. This is useful when a client wants to build on top of the pipeline you set up, or when you are handing off a project at the end of an engagement. From your organization dashboard, creating a project and generating scoped keys is straightforward. Each project can have multiple keys (production, staging, development), and each key is independently revocable. The scoped key works exactly like an organization-level key — same API endpoints, same request format, same response format. The only difference is that usage is tracked against the project: const fleetClient = new IterationLayer({ apiKey: "il_proj_fleet_mgmt_prod_key", }); const result = await fleetClient.extract({ files: [ { type: "url", name: "traffic-fine.pdf", url: "https://storage.example.com/fleet-mgmt/fines/FINE-2026-0472.pdf", }, ], schema: { fields: [ { name: "vehicle_plate", description: "License plate number of the vehicle", type: "TEXT", }, { name: "violation_date", description: "Date the traffic violation occurred", type: "DATE", }, { name: "fine_amount", description: "Amount of the fine including fees", type: "CURRENCY_AMOUNT", }, { name: "violation_country", description: "Country where the violation occurred", type: "COUNTRY", }, ], }, }); This request is identical to any other extraction call. The scoping happens at the authentication layer — the API key determines which project the usage is attributed to. No additional headers, no project ID parameters, no routing configuration. Budget caps are the safety mechanism that lets you sleep at night when five automated pipelines are running unattended. Automated pipelines fail in two directions: they stop working (which you notice immediately) or they start working too much (which you notice on the invoice). A bug in a retry loop that resubmits the same 50-page document 200 times. A client who uploads a batch of 10,000 documents when you scoped the project for 500/month. A webhook configuration that creates a feedback loop between two services. Each of these scenarios can consume your entire credit pool in hours. Without per-project budget caps, one runaway project affects every project. The shared credit pool hits zero, and all five clients' pipelines stop processing. With per-project budget caps, the runaway project hits its cap and returns a 402 error. The other four projects continue operating normally. You get alerted, investigate the cause, and fix it — without a fire drill across your entire client portfolio. Budget caps are set per project in your organization dashboard. You specify the maximum number of credits the project can consume per billing period. When a project exceeds its cap, API requests using that project's keys return a 402 status code. The response body tells you the cap has been reached. Other projects on your account are completely unaffected — each budget cap is independent. You can adjust the cap at any time. If a client's volume increases mid-month, you raise the cap from the dashboard. If you need to temporarily pause a project's processing, set the cap to zero. Budget caps should be set with headroom above expected usage, but tight enough to catch anomalies. A good rule of thumb: Expected monthly usage Budget cap 500 credits 750-1,000 credits 2,000 credits 3,000-4,000 credits 10,000 credits 12,000-15,000 credits The cap should be high enough that normal usage variation does not trigger it, but low enough that a runaway pipeline gets caught before it consumes a meaningful portion of your credit pool. Budget caps are a safety net, not a monitoring strategy. You should track per-project usage proactively, not just wait for caps to trigger. A healthy monitoring setup tracks: Daily credit consumption per project (compare to historical average) Credit consumption rate (credits per hour — sudden spikes indicate anomalies) Remaining credits in the organization pool (to forecast when you need to top up) Per-API breakdown per project (to understand which operations drive costs) Accurate client billing is the difference between an agency that makes money on processing and one that subsidizes it unknowingly. The most straightforward billing model for agencies: calculate the actual processing cost for each client project, add your margin, and invoice. Step 1: Determine your per-credit cost. This depends on your plan — see Credits & Pricing for the current rates per plan and pay-as-you-go tiers. Step 2: Pull per-project usage from the dashboard. Each project's usage is tracked separately — total credits consumed, broken down by API and by time period. Step 3: Calculate the client cost. Multiply the project's credit consumption by your per-credit cost, then add your margin. Example calculation for Client A (Fleet Management): Operation Monthly volume Credits per request Total credits Traffic fine extraction (avg. 2 pages) 800 documents 2 per document 1,600 Summary report generation 4 monthly reports 2 per report 8 Fine notice image processing 200 images 1 per image 200 Total 1,808 Look up your per-credit rate in Credits & Pricing, multiply by total credits, and you have your processing cost. Add a 3x markup (covering your integration work, support, and margin) to get the client-facing price. Many agencies prefer fixed-fee pricing for client predictability. The unified credit system makes this straightforward to forecast. Step 1: Estimate monthly volume during project scoping. "Client B expects approximately 300 insurance claims per month, each averaging 5 pages." Step 2: Calculate expected credit consumption. Operation Monthly volume Credits Claim extraction (5 pages avg.) 300 claims 1,500 Claim summary generation 300 summaries 600 Total 2,100 Step 3: Set a fixed monthly fee that covers the expected consumption, a volume buffer (20-30%), your margin, and your integration/support time. Multiply 2,100 credits by your per-credit rate, add a 25% volume buffer, then apply your margin. Round to a clean number for the client proposal. Step 4: Set the budget cap slightly above the buffered volume (e.g., 2,800 credits) to protect against overages without cutting off normal processing. For clients with highly variable volume, charge per unit processed: "$0.15 per invoice processed" (covering extraction + report generation credits + margin) "$0.05 per image transformed" (covering transformation credits + margin) Per-project usage tracking makes this easy to reconcile. At the end of the month, pull the project's usage, calculate the per-unit count, and invoice. Here is the practical workflow for an agency managing multiple client projects on Iteration Layer. Step 1: Create the project. Log into your organization dashboard Create a new project (name it after the client or engagement) Generate a production API key and a development/staging key Set an initial budget cap based on your scope estimate Step 2: Build the pipeline. Because every Iteration Layer API follows the same patterns — same auth, same request format, same response format, same SDK methods — you are not learning a new tool. You are configuring an existing one. For a client that needs invoice extraction and report generation, the pipeline code looks like this: const client = new IterationLayer({ apiKey: "il_proj_newclient_prod_key", }); // Step 1: Extract invoice data const extractionResult = await client.extract({ files: [ { type: "url", name: "invoice.pdf", url: "https://storage.example.com/newclient/invoices/INV-001.pdf", }, ], schema: { fields: [ { name: "vendor_name", description: "Name of the vendor", type: "TEXT", }, { name: "line_items", description: "Invoice line items", type: "ARRAY", fields: [ { name: "description", description: "Item description", type: "TEXT", }, { name: "amount", description: "Line item amount", type: "CURRENCY_AMOUNT", }, ], }, { name: "total", description: "Invoice total including VAT", type: "CURRENCY_AMOUNT", }, ], }, }); // Step 2: Generate summary report from extracted data const report = await client.generateDocument({ format: "pdf", document: { metadata: { title: "Invoice Summary Report", }, content: [ { type: "headline", level: "h1", text: "Invoice Summary", }, { type: "paragraph", markdown: `**Vendor:** ${extractionResult.vendor_name.value}\n\n**Total:** ${extractionResult.total.value}`, }, ], }, }); Notice the composability: the extraction result feeds directly into the document generation request. Same API key, same client instance, same error handling patterns. The output of one API becomes the input to the next without format conversion or middleware. Step 3: Test and deploy. Use the development API key for testing. The development key tracks usage separately from production (if you set up separate dev projects), so test runs do not pollute your production usage metrics or hit your client's budget cap. Usage review (15 minutes per project): Check per-project usage in the dashboard Compare to budget cap and expected volume Flag any anomalies (sudden spikes or drops) Export usage data for client invoicing Client billing (5 minutes per project): Pull the project's credit consumption for the billing period Apply your billing model (cost-plus, fixed-fee, or per-unit) Generate the client invoice Budget cap review (5 minutes per project, quarterly): Compare actual usage to cap over the last quarter Adjust caps based on trends (growing clients need higher caps) Review any cap-triggered incidents and their root causes The architecture scales linearly. Each new project is: A new project in the dashboard (2 minutes) Two new API keys — production and development (1 minute) A budget cap configuration (1 minute) Pipeline code that follows the same patterns as every other project The operational overhead per project is roughly constant. Twenty projects takes the same 15-20 minutes of monthly management per project as five projects. There is no exponential increase in coordination, credential management, or billing complexity. When a client engagement ends or you are handing off the pipeline to the client's internal team: Transfer the project. The client creates their own Iteration Layer account. You help them set up the project on their account and migrate the API keys. Or keep the project on your account. If you are providing ongoing managed services, the project stays on your account. The client pays you; you pay for the credits. Revoke old keys. Once the handoff is complete, revoke the old project keys. Other projects are unaffected. The handoff is clean because the project isolation is real. There are no shared configurations, no cross-project dependencies, no entangled credentials. It is tempting to use one API key for "all development" or "all small clients." Do not do this. Per-project usage tracking only works if each project has its own key. The five minutes saved by sharing a key will cost hours of manual usage attribution at billing time. If the budget cap triggers during normal operation, it disrupts the client's pipeline and erodes trust. Set caps with at least 50% headroom above expected peak usage. A cap that never triggers is still valuable — it protects against catastrophic failure modes, not normal variation. Development and testing usage should not be mixed with production usage. Create separate development projects (or use separate keys with clearly labeled purposes) so that your test runs do not inflate the usage numbers you use for client billing. If some months a client uses very little, do not bill them the proportional plan cost. Bill them based on actual credit consumption (at your marked-up rate) or a minimum monthly fee. This keeps pricing fair and defensible. Every client project should have a brief document that describes: what the pipeline does, which API calls it makes, what the expected monthly volume is, and what the budget cap is set to. When you hand off a project — or when a team member takes over — this document prevents knowledge loss. For agencies serving EU clients, the multi-project architecture also simplifies compliance documentation. You sign one Data Processing Agreement with Iteration Layer. That DPA covers all processing across all projects. You do not need a separate vendor DPA per client engagement. In your DPA with each client, you list Iteration Layer as a sub-processor with the same details: Sub-processor: Iteration Layer Processing location: EU (see Security for details) Data processed: Document content for extraction/generation (zero retention) Retention: None. Files processed in memory, discarded immediately. This section is identical across client DPAs. It becomes a standard clause in your agency's DPA template. If you are an agency evaluating Iteration Layer for multi-client document processing, here is the practical starting point: Sign up for a free account. Trial credits are available per API — enough to prototype a full pipeline without committing to a subscription. Create your first project for an existing or upcoming client engagement. Build one pipeline. Extract data from a client document, generate a report from the extracted data. See how the composability works in practice. Add a second project for a different client. Notice that the only things that change are the API key and the extraction schema — the integration code, error handling, and response parsing are identical. Evaluate the operational overhead. Compare the per-project management time to your current multi-vendor setup. The docs cover every API endpoint with request/response examples. The TypeScript, Python, and Go SDKs handle auth and error parsing.