
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
inflow-api-types
Advanced tools
TypeScript types for Inflow Inventory API - validated against live API, not just swagger.json
TypeScript types for the Inflow Inventory API that are actually correct.
Types derived from OpenAPI spec, then validated against the live API with corrections for documented inaccuracies. Every schema has been integration-tested - these types reflect what the API actually returns, not what swagger.json claims.
Inflow's swagger.json has inaccuracies: wrong enum casing, missing fields, incorrect nullability. Auto-generated types from that spec would be silently wrong.
This package uses Zod schemas + integration tests to discover the truth:
.parse() against live API responseThe result: types you can trust, with optional runtime validation if you want it.
No build step required. This is pure JavaScript with Zod schemas - install and use immediately.
Install via git dependency:
# npm
npm install git+https://github.com/ldraney/inflow-api-types.git
# yarn
yarn add git+https://github.com/ldraney/inflow-api-types.git
# pnpm
pnpm add git+https://github.com/ldraney/inflow-api-types.git
Or add directly to package.json:
{
"dependencies": {
"inflow-api-types": "github:ldraney/inflow-api-types"
}
}
Pin a specific version:
{
"dependencies": {
"inflow-api-types": "github:ldraney/inflow-api-types#v1.0.0"
}
}
import { ProductGET, ProductPUT, ProductConstraints } from 'inflow-api-types/products';
// Validate API response
const response = await fetch(`${BASE_URL}/products/${id}`, { headers });
const data = await response.json();
const product = ProductGET.parse(data); // Throws if invalid
// Safe parsing (no throw)
const result = ProductGET.safeParse(data);
if (result.success) {
console.log(result.data.name);
} else {
console.error(result.error);
}
// Validate before PUT
const payload = ProductPUT.parse({
productId: crypto.randomUUID(),
name: 'New Product',
itemType: 'stockedProduct',
});
await fetch(`${BASE_URL}/products`, {
method: 'PUT',
body: JSON.stringify(payload),
headers,
});
When building Inflow-related projects with AI assistance, add this to your project's CLAUDE.md or equivalent instructions file:
## Inflow API Integration
This project uses `inflow-api-types` for Inflow Inventory API validation.
### Key Resources
- Schemas: `node_modules/inflow-api-types/` - All Zod schemas
- API Docs: `node_modules/inflow-api-types/CLAUDE.md` - Detailed entity documentation
- Swagger: `node_modules/inflow-api-types/swagger.json` - OpenAPI spec (note: has inaccuracies)
### Schema Pattern
Each entity has:
- `{Entity}GET` - Response validation
- `{Entity}PUT` - Request validation
- `{Entity}Includes` - Available ?include= options
- `{Entity}Filters` - Available ?filter[x]= options
- `{Entity}Constraints` - Read-only/immutable fields
### Trust the Schemas
The schemas in this package have been tested against the live API.
When swagger.json conflicts with these schemas, trust the schemas.
### Common Gotchas
- Enum values are camelCase (e.g., 'stockedProduct' not 'StockedProduct')
- Decimal fields return as strings (e.g., "19.99" not 19.99)
- Many fields marked required in swagger are actually optional
- Some ?include= options don't work on certain entities
| Entity | Import Path |
|---|---|
| Product | inflow-api-types/products |
| Vendor | inflow-api-types/vendors |
| Customer | inflow-api-types/customers |
| Purchase Order | inflow-api-types/purchase-orders |
| Sales Order | inflow-api-types/sales-orders |
| Manufacturing Order | inflow-api-types/manufacturing-orders |
| Entity | Import Path |
|---|---|
| Stock Transfer | inflow-api-types/stock-transfers |
| Stock Adjustment | inflow-api-types/stock-adjustments |
| Product Cost Adjustment | inflow-api-types/product-cost-adjustments |
| Entity | Import Path |
|---|---|
| Stock Count | inflow-api-types/stock-counts |
| Count Sheet | inflow-api-types/count-sheets |
| Stockroom Scan | inflow-api-types/stockroom-scans |
| Stockroom User | inflow-api-types/stockroom-users (GET only) |
| Entity | Import Path |
|---|---|
| Custom Field Definition | inflow-api-types/custom-field-definitions |
| Custom Field Dropdown Options | inflow-api-types/custom-field-dropdown-options |
| Custom Fields | inflow-api-types/custom-fields |
| Webhook | inflow-api-types/webhooks |
| Entity | Import Path |
|---|---|
| Category | inflow-api-types/reference |
| Location | inflow-api-types/reference |
| Currency | inflow-api-types/reference |
| Pricing Scheme | inflow-api-types/reference |
| Payment Terms | inflow-api-types/reference |
| Tax Code | inflow-api-types/reference |
| Taxing Scheme | inflow-api-types/reference |
| Operation Type | inflow-api-types/reference |
| Adjustment Reason | inflow-api-types/reference |
| Team Member | inflow-api-types/reference |
| Unit of Measure | inflow-api-types/reference |
| Entity | Import Path |
|---|---|
| Product Summary | inflow-api-types/product-summary |
import { ProductGET, ProductIncludes } from 'inflow-api-types/products';
// Check available includes
console.log(ProductIncludes);
// {
// inventoryLines: { description: '...', adds: ['inventoryLines', 'totalQuantityOnHand'] },
// prices: { description: '...', adds: ['prices'] },
// vendorItems: { description: '...', adds: ['vendorItems'] },
// ...
// }
// Fetch with includes
const response = await fetch(
`${BASE_URL}/products?include=inventoryLines,prices`,
{ headers }
);
const products = ProductGET.array().parse(await response.json());
import { ProductFilters } from 'inflow-api-types/products';
// Check available filters
console.log(ProductFilters);
// {
// name: { type: 'string', description: 'Filter by name' },
// isActive: { type: 'boolean', description: 'Filter by active status' },
// smart: { type: 'string', description: 'Smart search across multiple fields' },
// ...
// }
// Fetch with filters
const response = await fetch(
`${BASE_URL}/products?filter[isActive]=true&filter[smart]=widget`,
{ headers }
);
import { ProductPUT, ProductConstraints } from 'inflow-api-types/products';
// See what's read-only (don't send these on PUT)
console.log(ProductConstraints.readOnly);
// ['lastModifiedDateTime', 'lastModifiedById', 'totalQuantityOnHand', 'cost', ...]
// See what's required for create vs update
console.log(ProductConstraints.required);
// { create: ['productId', 'name', 'itemType'], update: ['productId'] }
// See what can't change after creation
console.log(ProductConstraints.immutable);
// ['itemType', 'trackSerials']
import { z } from 'zod';
import { ProductGET, ProductPUT } from 'inflow-api-types/products';
// Infer types from schemas
type Product = z.infer<typeof ProductGET>;
type ProductInput = z.infer<typeof ProductPUT>;
// Use in functions
function processProduct(product: Product) {
console.log(product.name, product.sku);
}
async function createProduct(input: ProductInput) {
const validated = ProductPUT.parse(input);
// ... send to API
}
import { ProductGET } from 'inflow-api-types/products';
import { ZodError } from 'zod';
try {
const product = ProductGET.parse(apiResponse);
} catch (error) {
if (error instanceof ZodError) {
// Schema validation failed
console.error('Validation errors:', error.errors);
// [{ path: ['name'], message: 'Required', code: 'invalid_type' }]
} else {
throw error;
}
}
import { z } from 'zod';
import {
ProductGET,
ProductPUT,
ProductIncludes,
} from 'inflow-api-types/products';
class InflowClient {
constructor(apiKey, companyId) {
this.baseUrl = `https://cloudapi.inflowinventory.com/${companyId}`;
this.headers = {
Authorization: `Bearer ${apiKey}`,
Accept: 'application/json;version=2025-06-24',
'Content-Type': 'application/json',
};
}
async getProduct(id, includes = []) {
const url = new URL(`${this.baseUrl}/products/${id}`);
if (includes.length) {
url.searchParams.set('include', includes.join(','));
}
const res = await fetch(url, { headers: this.headers });
if (!res.ok) throw new Error(`API error: ${res.status}`);
return ProductGET.parse(await res.json());
}
async upsertProduct(product) {
const payload = ProductPUT.parse(product);
const res = await fetch(`${this.baseUrl}/products`, {
method: 'PUT',
headers: this.headers,
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`API error: ${res.status}`);
return ProductGET.parse(await res.json());
}
}
| Setting | Value |
|---|---|
| Base URL | https://cloudapi.inflowinventory.com/{companyId} |
| Auth | Authorization: Bearer {API_KEY} |
| Version | Accept: application/json;version=2025-06-24 |
| Rate Limit | 60 requests/minute |
The swagger.json included has known inaccuracies. These schemas reflect the actual API behavior:
| Issue | swagger.json | Actual API |
|---|---|---|
| Enum casing | StockedProduct | stockedProduct |
| Status values | Open, InTransit | open, inTransit |
| Custom field types | Text, Dropdown | text, dropdown |
| Decimal fields | type: number | Returns string "19.99" |
| Image URLs | Not nullable | Can be null |
| Undocumented fields | Missing | trackLots, trackExpiry, lotId |
# Run all tests (requires INFLOW_API_KEY and INFLOW_COMPANY_ID env vars)
npm test
# Run specific entity tests
npm run test:products
npm run test:vendors
See CLAUDE.md for:
MIT
FAQs
TypeScript types for Inflow Inventory API - validated against live API, not just swagger.json
The npm package inflow-api-types receives a total of 1 weekly downloads. As such, inflow-api-types popularity was classified as not popular.
We found that inflow-api-types demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.