Generate an SDK with custom code using the Postman CLI
This guide explains how to use the Postman CLI to generate an SDK from a Postman Collection, add custom code to the generated SDK, and regenerate the SDK while preserving your custom edits.
The SDK generator supports multiple programming languages, including TypeScript, Python, Java, Kotlin, C#, Go, PHP, Ruby, and Rust. The examples in this guide use generic syntax that can be adapted to any supported language.
Use cases for custom code include adding utility methods, custom logging, custom READMEs, or any additional logic that you want to maintain across SDK regenerations.
The postman sdk generate command generates a client SDK from a Postman Collection or API specification. Change tracking is included by default and enables the CLI to detect your local edits and merge them with the newly generated code on subsequent runs. The CLI uploads your local edits as custom code before triggering a new build.
Custom code SDKs are generated with the same structure as regular SDKs, but with additional handling to preserve user edits:
-
Customizations are applied after code formatting to prevent user-added custom code from causing the code formatter to fail, thereby allowing users to define their own formatting and SDK layout.
-
Developers’ edits to files are intended to persist, treating the local file system like a GitHub repository. Updates from the SDK generator are applied alongside user changes, and any conflicts are marked for users to resolve.
These changes don’t impact the size of the SDK because the last build artifact is retrieved from the database.
Follow the steps below to generate an SDK with custom code preserved across regenerations.
Step 1: Generate the initial SDK
The following command generates an SDK from a Postman Collection. Replace <language> with your preferred --language / -l value: typescript, python, java, kotlin, csharp (C#), go, php, ruby, or rust.
This example uses TypeScript (-l typescript):
The CLI output shows the progress of the build, including any warnings or issues encountered:
After the build completes, the CLI prints a build log summary listing any warnings or issues encountered:
Endpoints in the collection that do not have a URL are excluded from the generated SDK. To include them, add a URL to the request in the collection before regenerating.
Once the build succeeds, the CLI downloads the generated SDK to the output directory:
The generated SDK is saved to ./sdks/<language>/ (for example, ./sdks/typescript/) and includes the following structure:
.sdk-gen/— Internal SDK generation metadatadocumentation/— Auto-generated API documentationexamples/— Usage examples- Dependencies — SDK dependency artifacts (for example,
node_modules/for TypeScript orrequirements.txtfor Python) - Build files — Build and utility scripts
- Source files — Generated source files, organized into service modules (for example,
services/payment/,services/users/,services/billing/) - Configuration files — Example environment configuration (for example,
.env.example)
Step 2: Add custom code to the SDK
After the initial generation, you can edit the generated SDK source files to add custom logic. These edits are preserved on subsequent regenerations when you rerun the SDK generation command.
The following examples use TypeScript-like pseudocode to illustrate where custom code can be added in a generated SDK. Adapt the syntax, type system, and idioms to your chosen language’s conventions.
Example 1: Add custom logging methods
To add a custom logging method to a service class, use the following TypeScript-like example based on a PaymentService file such as sdks/<language>/src/services/payment/payment-service.<ext>, then adapt it to your target language:
You can then call this method from any service method within the class:
Example 2: Customize the existing README for branding
You can also customize the auto-generated README file to add branding, company-specific information, or additional usage examples. The SDK generates a basic README at sdks/<language>/README.md, which you can modify.
Open the README file and add your custom content. For example, you can add a company logo, installation instructions, company-specific authentication details, enterprise support information, and relevant links.
These customizations will be preserved when you regenerate the SDK.
Example 3: Add custom data transformation utilities
You can add utility methods to transform API responses or prepare request data. This example shows TypeScript modifications to sdks/<language>/src/services/payment/payment-service.<ext>:
This adds data transformation capabilities that format API responses into more user-friendly structures, including currency formatting and computed fields.
Example 4: Add custom validation and business logic
You can add business rule validation and custom logic to service methods. This TypeScript example shows modifications to sdks/typescript/src/services/payment/payment-service.ts:
This adds custom business rule validation and audit logging that wraps the generated SDK methods with additional logic specific to your application needs.
When implementing audit logging, be careful to avoid logging sensitive information such as full customer IDs, payment tokens, personal data, or API keys. In production environments, consider redacting or omitting these fields entirely, or use structured logging with appropriate data classification.
Step 3: Regenerate the SDK with custom code preserved
When you run postman sdk generate, the CLI automatically detects your local edits and handles the merge:
If the SDK output directory already exists, the CLI will prompt before overwriting:
After confirming, the SDK is downloaded again with your custom code merged in:
Step 4: Resolve merge conflicts (if any)
When both you and the generator change the same lines in a file, the CLI handles the conflict based on the conflictStrategy setting. With the default mark strategy, the CLI adds conflict markers to the file, allowing you to manually resolve the conflicts. The conflict markers look like this:
In this example, the user modified the getPet method to first check a local cache before making an API call, while the generator updated the method to return a Promise that resolves with the API response. The conflict markers indicate that both versions changed the same lines of code, and manual resolution is needed to determine how to merge these changes.
The CLI reports files with conflicts after download:
You can then open the file, review the conflicting changes, and edit the code to resolve the conflict. After resolving, save the file and continue using the SDK as normal.
How change detection works
Each generated SDK has a .manifest.json in its root. When change tracking is enabled, this file includes a fileHashes field — a map of every generated file to its SHA-256 hash:
On the next regeneration, the CLI does the following:
-
Reads
fileHashesfrom.manifest.json. -
Computes the current hash of each file on disk.
-
Compares the files. Any mismatch means the file was edited.
-
Scans for user-added files not in the manifest.
-
Checks for files in the manifest that no longer exist on disk (user-deleted).
Only the changed files are uploaded. The generator uses the previous build’s output as the merge base for a three-way merge.
When you regenerate, the CLI uploads a zip file with the following structure:
Only the changed or added files and metadata are uploaded and not the entire SDK.
The following directories are excluded from change detection and hashing to avoid tracking dependencies and build output.
-
Dependencies and packages:
node_modulesvendor.venv
-
Build outputs:
distbuildtargetbinobj
-
Build tools and cache:
__pycache__.gradle
-
Internal and version control:
.sdk-gen.git
How change tracking works
The customCode section of the SDK configuration controls change-tracking and merge behavior. The CLI terminal output shows the effective configuration being applied. This example corresponds to running with --conflict-strategy mark, which adds conflict markers to files when both the user and generator modify the same lines:
The following is priority order for these settings, from highest to lowest:
- CLI flags (for example,
trackChangesis set totrueandconflictStrategydefaults to"mark").- If you run the command with
--no-track-changes, change tracking will be turned off for that run. This means the generator will perform a clean regeneration that overwrites all files, and no merge will be attempted to preserve user edits. - If you run the command with
--conflict-strategy ours, the conflict strategy will be set to"ours"for that run, and the generator will keep your changes and discard the generator’s changes.
- If you run the command with
customCodevalues set in the config file.- Setting
"trackChanges": falseis equivalent to--no-track-changes. - Setting
"noMerge": trueis equivalent to--no-merge.
- Setting
This means CLI flags always override values in the config file.
Limitations
Change tracking requires the generator to support writing fileHashes to .manifest.json. This is enabled by default on the server side.
The three-way merge requires a previous build artifact to exist in the cloud. If the previous build was cleaned up, customizations are applied as-is (no merge, just overlay).
Binary files are skipped during conflict scanning.