Link Matching
- Elisha Antunes
- Jun 7
- 2 min read
Updated: Jun 23
When testing APIs that model real-world relationships, it’s not enough to check individual fields — you often need to validate how different objects relate to each other. In my Freelance API project, every project object has an eventId, and every certificateHolder must reference one or more of those eventIds.
The requirement is simple: all project eventIds must be accounted for in the certificate holder section.
This post walks through how I used Postman to dynamically generate valid data and verify that these linked relationships are always honored — even as the number of projects changes.
Rule Breakdown
Projects | Valid Certificate Holder Patterns |
|---|---|
1 | One certificate holder with the single eventId |
2 | One holder with both eventIds, or two holders with one each |
3 | One holder with all three eventIds, or two holders (2+1 split) |
Step 1: Generate Unique Event IDs
const projectCount = Math.floor(Math.random() * 3) + 1;
const eventIds = [];
for (let i = 0; i < projectCount; i++) {
eventIds.push(pm.variables.replaceIn("{{$guid}}"));
}Step 2: Attach Event IDs to Projects
const projects = eventIds.map((id, index) => ({
title: `Project ${index + 1}`,
industry: "Web Development",
startDate: "2025-06-01",
endDate: "2025-06-10",
value: 7500 + index * 1000,
eventId: id
}));
pm.collectionVariables.set("projects", JSON.stringify(projects));Certificate Holder Logic Explained
The certificate holder generation logic dynamically adjusts based on how many projects are present. This guarantees that all eventIds are referenced in valid combinations, per the business rules.
Case 1: projectCount === 1
A single project must be referenced by a single certificate holder:
certificateHolders.push({
eventIds: [{ id: eventIds[0] }]
});Case 2: projectCount === 3
We allow two valid configurations:
One certificate holder referencing all 3 eventIds
Two certificate holders, one with 2 IDs and one with the remaining ID
This logic is randomized for variety:
if (choice < 0.5) {
// One cert holder with all 3 eventIds
} else {
// Cert A gets 2 IDs, Cert B gets 1 ID
}This ensures we always achieve a full match, but not in a rigid pattern—just like real-world behavior.
Case 3: projectCount === 2
The logic here allows:
One certificate holder listing both event IDs, or
Two separate holders, each linked to one project
if (choice > 0.5) {
// One cert with both eventIds
} else {
// One cert per eventId
}All paths result in complete linkage of eventIds to at least one cert holder.
Post-request Validation Script
To enforce this linkage after the request is sent:
const projects = pm.request.body ? JSON.parse(pm.request.body.raw).projects : [];
const certs = pm.request.body ? JSON.parse(pm.request.body.raw).certificateHolders : [];
const projectIds = projects.map(p => p.eventId);
const certIds = certs.flatMap(c => c.eventIds.map(e => e.id));
pm.test("Every project eventId is linked in certificate holders", () => {
projectIds.forEach(id => pm.expect(certIds).to.include(id));
pm.expect(certIds.length).to.be.greaterThanOrEqual(projectIds.length);
});
Takeaways
This approach shows how you can:
Dynamically generate and connect related data across arrays
Simulate realistic business logic within your test setup
Validate cross-object relationships with clarity and confidence
