Lab - Postman Company Management Workflow

Plan: B2B Developer

Lesson 9 of 18 · 45 min

Introduction

In the previous lab, you created a workflow to simulate a customer login. Now you’ll use that authentication process as you build out common storefront tasks for managing addresses and customers.

Prerequisites

  • A BigCommerce sandbox store or trial store, or a full production store
  • B2B Edition enabled in your store
  • Postman or a similar API client
  • An existing Postman environment, collection, and headers preset as configured in previous labs

In this lab, you will:

  • Create API requests to handle company address and user management
  • Implement Postman scripts to automate values used in API requests

Postman Recap

As a reminder, the “Admin Login” and “User Company” requests you created in the previous lab should authenticate the Admin user (per the admin email_and admin password_variables set on your collection) and store the following environment variables, which will be needed for various future requests:

  • b2b_storefront_token
  • b2b_logged_in_email
  • b2b_logged_in_id
  • bc_logged_in_id
  • b2b_logged_in_company_id

If you don’t currently have values set for these environment variables, or if at any time you find your current authentication token has expired, re-run the “Admin Login” and “User Company” requests.

Step 1: Get Company Addresses

Like most of the requests you’ll practice with from here out, the following request to fetch a list of addresses relies on the user context of the authentication token obtained from login to return only the address records relevant to the user’s company.

  1. Create a new HTTP request and save it to your collection with the name “Get Addresses.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Auth Type, Headers (using your previously created “GraphQL” preset), and Body type.
  3. Enter the following query.
query GetAddresses(
$companyId: Int!,
$limit: Int,
$after: String
) {
addresses(
companyId: $companyId,
first: $limit,
after: $after
) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
edges {
node {
id
firstName
lastName
isShipping
isDefaultShipping
isBilling
isDefaultBilling
addressLine1
addressLine2
city
state
stateCode
country
countryCode
zipCode
phoneNumber
label
}
}
}
}
  1. Enter the following in the GraphQL Variables panel.
{
"companyId": {{b2b_logged_in_company_id}},
"limit": 5,
"after": null
}

The GraphQL arguments and variables are configured to easily facilitate pagination; just replace the value of “after” with a valid endCursor from a previous response.

  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const result = pm.response.json().data?.addresses;
pm.test('Total count includes at least one address', () => {
pm.expect(
result?.totalCount
).to.be.greaterThan(0);
});
let firstAddress = null;
if (Array.isArray(result?.edges)) {
firstAddress = result.edges[0]?.node;
}
pm.test('Response includes at least one address with an ID', () => {
pm.expect(
firstAddress?.id
).to.be.a('string');
});
  1. Send the request and verify that all tests succeed.

You should see at least one address represented in the response: the initial address you configured in your initial “Create Company” request.

Step 2: Create an Address

  1. Create a new HTTP request and save it to your collection with the name “Create Shipping Address.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Auth Type, Headers (using your previously created “GraphQL” preset), and Body type.
  3. Enter the following query.
mutation CreateAddress(
$companyId: Int!,
$firstName: String!,
$lastName: String!,
$addressLine1: String!,
$addressLine2: String,
$country: String!,
$countryCode: String!,
$state: String!,
$stateCode: String,
$city: String!,
$zipCode: String!,
$phoneNumber: String,
$isShipping: Int,
$isBilling: Int,
$isDefaultShipping: Int,
$isDefaultBilling: Int,
$label: String,
$company: String
) {
addressCreate(
addressData: {
companyId: $companyId,
firstName: $firstName,
lastName: $lastName,
addressLine1: $addressLine1,
addressLine2: $addressLine2,
country: $country,
countryCode: $countryCode,
state: $state,
stateCode: $stateCode,
city: $city,
zipCode: $zipCode,
phoneNumber: $phoneNumber,
isShipping: $isShipping,
isBilling: $isBilling,
isDefaultShipping: $isDefaultShipping,
isDefaultBilling: $isDefaultBilling,
label: $label,
company: $company
}
) {
address {
id
label
isShipping
isBilling
isDefaultShipping
isDefaultBilling
}
}
}
  1. Enter the following in the GraphQL Variables panel.
{
"companyId": {{b2b_logged_in_company_id}},
"firstName": "Jack",
"lastName": "Doe",
"addressLine1": "456 Downtown Lane",
"addressLine2": "Ste 1",
"country": "United States",
"countryCode": "US",
"state": "Texas",
"stateCode": "TX",
"city": "Austin",
"zipCode": "78726",
"phoneNumber": "777-888-9999",
"isShipping": 1,
"isBilling": 0,
"isDefaultShipping": 1,
"isDefaultBilling": 0,
"label": "Main Shipping",
"company": "John's Widgets"
}
  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const address = pm.response.json().data?.addressCreate?.address;
pm.test('Response includes address with ID', () => {
pm.expect(
address?.id
).to.be.a('string');
});
pm.collectionVariables.unset('address_id');
pm.collectionVariables.set('address_id', address?.id);

This script captures the newly created address’s ID in the collection variable address_id, which will be used in the next requests to apply them automatically to the most recently created address. (Simply update the collection variable manually to manage a different address.)

  1. Send the request, verify that all tests succeed, and verify that the address_id variable is set on your collection.
  2. Re-run the “Get Addresses” query to observe the newly created address included in the results.

Try out paginating the “Get Addresses” request by setting “limit” to a low enough value (1, if your company only has two addresses) and updating the “after” variable with the endCursor of the first page response.

You can view the company in your B2B Edition admin, or by logging into your storefront with the Admin user’s credentials, to observe that the company now contains the new address, which is set as the default shipping address.

Step 3: Update and Delete an Address

  1. Create a new HTTP request and save it to your collection with the name “Update Address.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Auth Type, Headers (using your previously created “GraphQL” preset), and Body type.
  3. Enter the following query.
mutation UpdateAddress(
$companyId: Int!,
$addressId: Int!,
$firstName: String!,
$lastName: String!,
$addressLine1: String!,
$addressLine2: String,
$country: String!,
$countryCode: String!,
$state: String!,
$stateCode: String,
$city: String!,
$zipCode: String!,
$phoneNumber: String,
$isShipping: Int,
$isBilling: Int,
$isDefaultShipping: Int,
$isDefaultBilling: Int,
$label: String,
$company: String
) {
addressUpdate(
addressData: {
companyId: $companyId,
addressId: $addressId,
firstName: $firstName,
lastName: $lastName,
addressLine1: $addressLine1,
addressLine2: $addressLine2,
country: $country,
countryCode: $countryCode,
state: $state,
stateCode: $stateCode,
city: $city,
zipCode: $zipCode,
phoneNumber: $phoneNumber,
isShipping: $isShipping,
isBilling: $isBilling,
isDefaultShipping: $isDefaultShipping,
isDefaultBilling: $isDefaultBilling,
label: $label,
company: $company
}
) {
address {
id
label
isShipping
isBilling
isDefaultShipping
isDefaultBilling
}
}
}
  1. Enter the following initial values in the GraphQL Variables panel.
{
"companyId": {{b2b_logged_in_company_id}},
"addressId": {{address_id}},
"firstName": "Jack",
"lastName": "Doe",
"addressLine1": "456 Downtown Lane",
"addressLine2": "Ste 1",
"country": "United States",
"countryCode": "US",
"state": "Texas",
"stateCode": "TX",
"city": "Austin",
"zipCode": "78726",
"phoneNumber": "777-888-9999",
"isShipping": 1,
"isBilling": 0,
"isDefaultShipping": 1,
"isDefaultBilling": 0,
"label": "Main Shipping",
"company": "John's Widgets"
}
  1. Update the the GraphQL Variables panel with several changed values to test the process of updating the recently created address.
  2. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const address = pm.response.json().data?.addressUpdate?.address;
pm.test('Response includes address with ID', () => {
pm.expect(
address?.id
).to.be.a('string');
});
  1. Send the request and verify that all tests succeed.
  2. Use the “Get Addresses” query, or view the company details in the storefront or control panel, to verify the updated details of the address.

Now let’s also practice deleting an address.

  1. Create a new HTTP request and save it to your collection with the name “Delete Address.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Headers (using your previously created “GraphQL” preset), and Body type.
  3. In the Authorization tab, verify that Auth Type is set to “Inherit auth from parent.”
  4. Enter the following query.
mutation DeleteAddress(
$companyId: Int!,
$addressId: Int!
) {
addressDelete(
companyId: $companyId,
addressId: $addressId
) {
message
}
}
  1. Enter the following in the GraphQL Variables panel.
{
"companyId": {{b2b_logged_in_company_id}},
"addressId": {{address_id}}
}
  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const message = pm.response.json().data?.addressDelete?.message
pm.test('Operation was successful', () => {
pm.expect(
message
).to.eq('Success');
});
pm.collectionVariables.unset('address_id');
  1. Send the request and verify that all tests succeed.
  2. Use the “Get Addresses” query, or view the company details in the storefront or control panel, to verify the address was deleted.

You may choose to use the “Create Address” request again to restore the address or create multiple others.

Step 4: Get Users

  1. Create a new HTTP request and save it to your collection with the name “Get Users.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Auth Type, Headers (using your previously created “GraphQL” preset), and Body type.
  3. Enter the following query.
query GetUsers(
$companyId: Int!,
$limit: Int,
$after: String
) {
users(
companyId: $companyId,
first: $limit,
after: $after
) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
edges {
node {
id
bcId
firstName
lastName
email
phone
role
companyRoleId
companyRoleName
}
}
}
}
  1. Enter the following initial values in the GraphQL Variables panel.
{
"companyId": {{b2b_logged_in_company_id}},
"limit": 5,
"after": null
}
  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const result = pm.response.json().data?.users;
pm.test('Total count includes at least one user', () => {
pm.expect(
result?.totalCount
).to.be.greaterThan(0);
});
let firstUser = null;
if (Array.isArray(result?.edges)) {
firstUser = result.edges[0]?.node;
}
pm.test('Response includes at least one user with an ID', () => {
pm.expect(
firstUser?.id
).to.be.a('string');
});
  1. Send the request and verify that all tests succeed.

Like the “Get Addresses” query, this query is constrained to the context of the current user’s authentication token. Your company should have at least one user: the Admin user that was initially associated with it.

Step 5: Validate Junior Buyer Role and Email

In the next step, you’ll create a new user with the “Junior Buyer” role, simulating this task from the context of an Admin storefront user. Before doing so, we’ll take two steps to prepare:

  • Fetch the ID of the “Junior Buyer” role.
  • Check whether the email address of the new user is valid.

Junior Buyer is one of the pre-built roles that is assigned a hard-coded role ID (0). While you could create your Junior Buyer user using role: 0, a more forward compatible approach is to use companyRoleId. This approach will also support any custom roles you may create.

In order to specify companyRoleId, you’ll first need to fetch the available company roles and find the record ID for “Junior Buyer.”

  1. Create a new HTTP request and save it to your collection with the name “Get User Roles.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Auth Type, Headers (using your previously created “GraphQL” preset), and Body type.
  3. Enter the following query.
query GetUserRoles(
$companyId: Int!
) {
companyRoles(
companyId: $companyId
) {
edges {
node {
id
name
}
}
}
}
  1. Enter the following initial values in the GraphQL Variables panel.
{
"companyId": {{b2b_logged_in_company_id}}
}
  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const roles = pm.response.json().data?.companyRoles?.edges;
pm.test('Response includes roles', () => {
pm.expect(
roles?.length
).to.be.greaterThan(0);
});
pm.collectionVariables.unset('junior_role_id');
if (Array.isArray(roles)) {
const juniorRole = roles.find(role => role?.node?.name === 'Junior Buyer');
pm.test('Junior role found', () => {
pm.expect(
juniorRole?.node?.id
).to.be.a('string');
});
pm.collectionVariables.set('junior_role_id', parseInt(juniorRole?.node?.id));
}

This script searches the results set for the role with the name “Junior Buyer” and captures its ID with the collection variable junior_role_id, which can subsequently be used to create the new user.

  1. Send the request, verify that all tests succeed, and confirm that the junior_role_idvariable is set on your collection.

For your second step, you’ll validate the new user’s email address. To easily facilitate running the login mutation for the Junior Buyer user, you’ll store the email and password for this user on collection variables, just as you previously did with the Admin user.

  1. Open the collection and navigate to the Variables tab.
  2. Add the following variables. (Don’t forget to save the collection.)
Variable NameValue
junior_emailYour chosen email for a Junior Buyer user (different from the Admin user email)
junior_passwordYour chosen password
  1. Create a new HTTP request and save it to your collection with the name “Check Junior User Email.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Headers (using your previously created “GraphQL” preset), and Body type.
  3. In the Authorization tab, verify that****Auth Type is set to “Inherit auth from parent.”
  4. Enter the following query.
query CheckUserEmail(
$email: String!
) {
userEmailCheck(
email: $email
) {
userType
}
}
  1. Enter the following initial values in the GraphQL Variables panel.
{
"email": "{{junior_email}}"
}
  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const userType = pm.response.json().data?.userEmailCheck?.userType;
pm.test('User type exists', () => {
pm.expect(
userType
).to.be.a('number');
});
pm.test('Email is valid for new user', () => {
pm.expect(
[1, 2]
).to.include(userType);
});

The above script will ensure the response will only succeed on all tests if the user type is 1 or 2 (indicating the email address doesn’t match an existing user or matches a user not associated with a company).

  1. Send the request and verify that all tests succeed.

Step 6: Create the Junior Buyer User

Having captured the ID of the “Junior Buyer” role and validated the intended email address, you can now proceed with creating the user.

  1. Create a new HTTP request and save it to your collection with the name “Create Junior User.”
  2. Set the same configuration that was used for the previous requests, including the HTTP method, URL, Auth Type, Headers (using your previously created “GraphQL” preset), and Body type.
  3. Enter the following query.
mutation CreateUser(
$companyId: Int!,
$email: String!,
$firstName: String!,
$lastName: String!,
$companyRoleId: Int
) {
userCreate(
userData: {
companyId: $companyId,
email: $email,
firstName: $firstName,
lastName: $lastName,
companyRoleId: $companyRoleId
}
) {
user {
id
firstName
lastName
email
role
companyRoleId
companyRoleName
}
}
}
  1. Enter the following initial values in the GraphQL Variables panel. (Feel free to change the user details.)
{
"companyId": {{b2b_logged_in_company_id}},
"email": "{{junior_email}}",
"firstName": "Jack",
"lastName": "Doe",
"companyRoleId": {{junior_role_id}}
}
  1. In the Scripts tab, enter the following “Post-response” code.
pm.test('Response is not an error', () => {
pm.response.to.not.be.error;
pm.response.to.not.have.jsonBody("errors");
});
pm.test('Response is JSON with data', () => {
pm.response.to.have.jsonBody("data");
});
const user = pm.response.json().data?.userCreate?.user;
pm.test('Response includes user with ID', () => {
pm.expect(
user?.id
).to.be.a('string');
});
  1. Send the request and verify that all tests succeed.
  2. Re-run the “Get Users” request to observe the new Junior Buyer in the response.

Step 7: Log In as Junior Buyer

With your Junior Buyer user now assigned to your company, you can easily create a “Junior Login” request similar to your original “Admin Login” request, to allow for easily “toggling” your authentication between the two users.

Note, however, that your request to create the Junior Buyer user did not include setting a password. This reflects storefront behavior, where an Admin user can create a new user, but their password will ultimately be set when the user receives and acts on a welcome email.

  1. In the BigCommerce control panel, navigate to Customers and select the new Junior Buyer customer.
  2. Set the customer’s password (make sure it matches the value you have set for junior_password in your collection) and save the customer.
  3. Duplicate your “Admin Login” request and set the name of the new request to “Junior Buyer Login.”
  4. In the GraphQL Variables panel of the Body tab, change the JSON to the following.
{
"storeHash": "{{store_hash}}",
"email": "{{junior_email}}",
"password": "{{junior_password}}"
}

With the post-response script copied directly from the “Admin Login” request, this request will update the same environment variables, capturing the authentication token and other details when you “log in” as the Junior Buyer.

  1. Send the request and verify that all tests succeed.
  2. Re-run the “Get Users” request.

With your environment variables updated with an authentication token matching the Junior Buyer user, you should now see a “Permission denied” error in the response, since Junior Buyers do not have permission to view a company’s users.

With both an “Admin Login” and “Junior Buyer Login,” you can now easily switch between the two users, establishing the user context for any other requests you choose to run. Utilize this capability to observe the effects of different roles/permissions on the GraphQL behavior.

Taking It Further

Finish out your Users workflow by creating an “Update User” request utilizing the userUpdate mutation and a “Delete User” request utilizing the userDelete mutation.