Skip to content

Postman Collections: Organizing API Tests with Folders and Variables

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Postman Collections: Organizing API Tests with Folders and Variables. We cover key concepts, practical examples, and best practices to help you master this topic.

Postman collections group related API requests with folder hierarchies, collection-level variables, authentication templates, reusable scripts, and data-driven testing support for organized test suites.

What You'll Learn

How to structure collections with folders, use collection-level variables for shared configuration, create authentication templates, reuse pre-request and test scripts at the collection level, use data files for parameterized tests, and export/share collections.

Why It Matters

Well-organized collections are maintainable, reusable, and team-friendly. A clear folder structure mirrors the API domain, reduces duplication, and makes it easy to find and update tests. DodaTech organizes collections by API domain and by environment.

Real-World Use

A new team member opens the DodaTech API collection. They see folders for Users, Products, Orders, and Payments. Each folder has CRUD requests with shared authentication, environment-specific URLs, and consistent test patterns.

flowchart LR
    A["DodaTech API\nCollection"] --> B["Users\nFolder"]
    A --> C["Products\nFolder"]
    A --> D["Orders\nFolder"]
    A --> E["Auth\nFolder"]
    B --> F["Create User\nPOST"]
    B --> G["Get User\nGET"]
    B --> H["Update User\nPUT"]
    B --> I["Delete User\nDELETE"]
    E --> J["Login\nPOST"]
    E --> K["Refresh Token\nPOST"]
    style A fill:#ef7d31,color:#fff
    style B fill:#dbeafe,stroke:#2563eb
    style C fill:#dbeafe,stroke:#2563eb
    style D fill:#dbeafe,stroke:#2563eb

Collection Structure

DodaTech API Collection
  Variables:
    base_url: https://api.dodatech.com/v1
    api_version: v1
    timeout: 5000

  Auth (Folder - No Auth)
    Pre-request: (none)
    POST /auth/login
    POST /auth/refresh
    POST /auth/logout

  Users (Folder - Inherit Auth)
    Pre-request: Set auth header from token variable
    GET /users          (List users)
    POST /users         (Create user)
    GET /users/:id      (Get user by ID)
    PUT /users/:id      (Update user)
    DELETE /users/:id   (Delete user)

  Products (Folder - Inherit Auth)
    Pre-request: (inherit)
    GET /products       (List products)
    POST /products      (Create product)
    GET /products/:id   (Get product)

Collection-Level Variables

// Set collection variables in the collection settings
// Variables tab > Add

// Collection variables (accessible by all requests):
// base_url:     https://api.dodatech.com/v1
// api_key:      {{api_key}}  (inherited from environment)
// default_page_size: 20
// content_type: application/json

// Using collection variables in requests:
// URL: {{base_url}}/users
// Header: Content-Type: {{content_type}}

// Access in pre-request/test scripts:
const baseUrl = pm.collectionVariables.get("base_url");
const pageSize = pm.collectionVariables.get("default_page_size");
console.log(`Using API: ${baseUrl}, page size: ${pageSize}`);

// Set collection variables dynamically
pm.collectionVariables.set("created_user_id", jsonData.id);

Reusable Collection-Level Scripts

// Collection-level pre-request script (runs for every request)

// 1. Auto-attach authentication
const token = pm.environment.get("auth_token");
if (token) {
    pm.request.headers.add({
        key: "Authorization",
        value: `Bearer ${token}`,
        enabled: true
    });
}

// 2. Add common headers
const commonHeaders = {
    "X-Request-Id": require('uuid').v4 ? require('uuid').v4() : Date.now().toString(),
    "X-Api-Version": pm.collectionVariables.get("api_version"),
    "Accept": "application/json"
};
Object.keys(commonHeaders).forEach(key => {
    pm.request.headers.add({ key, value: commonHeaders[key] });
});

// 3. Log request details
console.log(`Request: ${pm.request.method} ${pm.request.url}`);
// Collection-level test script (runs for every request)

// 1. Common assertions for every response
pm.test("Response has valid status code", function () {
    const validCodes = [200, 201, 204, 400, 401, 403, 404];
    pm.expect(validCodes).to.include(pm.response.code);
});

pm.test("Response time within limit", function () {
    pm.expect(pm.response.responseTime).to.be.below(
        parseInt(pm.collectionVariables.get("timeout") || 5000)
    );
});

pm.test("Content-Type is JSON", function () {
    if (pm.response.code !== 204) {
        pm.response.to.have.header("Content-Type", "application/json");
    }
});

// 2. Log failed test details
if (pm.response.code >= 400) {
    console.warn(`Request failed: ${pm.response.code}`, pm.response.json());
}

Data-Driven Testing

// data.json - CSV or JSON data file for parameterized tests
[
  {
    "email": "user1@test.com",
    "name": "User One",
    "role": "admin",
    "expected_status": 201
  },
  {
    "email": "",
    "name": "User Two",
    "role": "user",
    "expected_status": 400
  },
  {
    "email": "invalid-email",
    "name": "User Three",
    "role": "user",
    "expected_status": 400
  }
]
// In the request body:
{
    "email": "{{email}}",
    "name": "{{name}}",
    "role": "{{role}}"
}

// In test script:
pm.test(`Create user ${pm.iterationData.get("email")} returns ${pm.iterationData.get("expected_status")}`, function () {
    pm.expect(pm.response.code).to.equal(
        parseInt(pm.iterationData.get("expected_status"))
    );
});

// Run with: Collection Runner > Select data file > Run
// Iteration 1: user1@test.com -> 201 (PASS)
// Iteration 2: "" -> 400 (PASS)
// Iteration 3: invalid-email -> 400 (PASS)

Common Mistakes

1. Flat Collection Structure

Putting all requests at the root level makes navigation impossible. Use folders to mirror your API structure (Users, Products, Orders) and sub-folders for related flows.

2. Duplicating Authentication Logic

Adding auth headers to every request individually is error-prone. Use collection-level pre-request scripts to attach authentication automatically.

3. Hardcoding Collection Variables

Collection variables are not secret-safe. Store API keys and tokens in environment variables, not collection variables. Use collection variables for non-sensitive defaults.

4. Not Using Data Files

Testing with the same data every time misses edge cases. Use data-driven testing with CSV/JSON files to test multiple input combinations in one run.

5. Ignoring Folder-Level Scripts

You can set pre-request and test scripts at the folder level. These run for all requests in that folder. Use this for folder-specific setup (e.g., admin auth for admin-only endpoints).

Practice Questions

  1. What is the difference between collection variables and environment variables?
  2. How do you run a collection with multiple data sets?
  3. Why use collection-level pre-request scripts?
  4. How do you organize a collection for a large API?

Answers:

  1. Collection variables are tied to the collection and shared when exported. Environment variables are environment-specific (dev, staging, prod). Use collection for defaults, environment for secrets and URLs.
  2. Create a JSON or CSV data file with rows of test data. In the Collection Runner, select the data file. Each row becomes an iteration with access via pm.iterationData.get("field").
  3. Collection-level scripts run for every request, avoiding duplication. Common uses: attach auth headers, add request IDs, set content type, log request details, and verify common response properties.
  4. Use folders per domain (auth, users, products, orders) with sub-folders per action (CRUD) or flow. Use collection-level scripts for shared logic, folder-level for domain-specific setup.

Challenge: Design and build a complete collection for an e-commerce API (30+ endpoints across 5 domains). Use folder hierarchy, collection-level auth and logging scripts, folder-level setup for admin/user roles, environment variables for dev/staging/prod, and data files for parameterized testing.

FAQ

How do I share a collection with my team?

Export as JSON (Collection > Export), publish to Postman Workspace, or sync with Postman Cloud. For version control, export and commit the JSON to your repo.

Can I import OpenAPI specs into Postman?

Yes, Postman can import OpenAPI (Swagger), RAML, and GraphQL schemas. Go to Import > File > Select OpenAPI spec. Postman generates a collection from the spec.

What is the maximum collection size?

Postman Cloud collections have a 10 MB limit. For larger collections, split by domain or export as files. Newman can run from file without cloud sync.

How do I store secrets in collections?

Do not store secrets in collections (they are exported as JSON). Store API keys, tokens, and passwords in environment variables. Environment files can be gitignored.

Can I nest folders in collections?

Yes, Postman supports nested folders up to 5 levels deep. Use sub-folders for related flows within a domain folder (e.g., Users > CRUD, Users > Auth Tests).

Mini Project

Build a structured Postman collection for a blog API (users, posts, comments, categories). Include: 4 domain folders with sub-folders, collection-level auth and logging scripts, folder-level test data setup, environment variables for dev/staging, data-driven tests for create operations, and export the collection as JSON for CI.

What's Next

Postman Scripts — advanced scripting techniques for Postman.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro