User Account Flow

A walkthrough of managing a user account — from viewing and updating profile information to checking loyalty, redeeming rewards, and verifying identity.

What you'll build

A complete account management flow that:

  1. Gets the user profile
  2. Updates profile information (name, date of birth)
  3. Updates the billing address
  4. Checks loyalty points and tier
  5. Views available rewards
  6. Applies a reward to the cart
  7. Checks identity verification status

Prerequisites

All endpoints in this flow require authentication (jwt_authenticated pipeline).


Setup

STORE_UUID="e87437f2-3e35-4738-af5e-6307e368255c"
BASE_URL="https://ecom-api.staging.blaze.me"
TOKEN="YOUR_JWT_TOKEN"
const STORE_UUID = "e87437f2-3e35-4738-af5e-6307e368255c";
const BASE_URL = "https://ecom-api.staging.blaze.me";
const token = "YOUR_JWT_TOKEN";

const headers = {
  "Content-Type": "application/vnd.api+json",
  Accept: "application/vnd.api+json",
  "X-Store": STORE_UUID,
  Authorization: `Bearer ${token}`,
};

Step 1: Get User Profile

Retrieve the authenticated user's full profile, including address, IDs, marketing preferences, and order history summary.

GET /api/v1/users/me

cURL

curl -X GET "$BASE_URL/api/v1/users/me" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN"

JavaScript

const profileRes = await fetch(`${BASE_URL}/api/v1/users/me`, { headers });

const { data: user } = await profileRes.json();
console.log(`${user.attributes.first_name} ${user.attributes.last_name}`);
console.log(`Email: ${user.attributes.email}`);
console.log(`Orders: ${user.attributes.num_orders}`);
console.log(`Type: ${user.attributes.customer_type_display}`);

Response

{
  "data": {
    "id": "123",
    "type": "users",
    "attributes": {
      "email": "jane@example.com",
      "first_name": "Jane",
      "last_name": "Doe",
      "phone_number": "+15551234567",
      "address": {
        "address": "123 Main St",
        "city": "Los Angeles",
        "state": "CA",
        "zip_code": "90001",
        "country": "US"
      },
      "date_of_birth": "1990-01-15T00:00:00Z",
      "num_orders": 12,
      "last_order_at": "2026-04-20T18:30:00Z",
      "confirmed_at": "2026-01-10T14:00:00Z",
      "is_active": true,
      "is_pos_confirmed": true,
      "customer_type": "recreational",
      "customer_type_display": "Recreational",
      "marketing_sms_opt_in": true,
      "marketing_email_opt_in": false,
      "billing_address": {
        "address": "123 Main St",
        "city": "Los Angeles",
        "state": "CA",
        "zip_code": "90001"
      },
      "is_anonymous": false
    },
    "relationships": {
      "documents": { "data": [] },
      "rewards": { "data": [] },
      "reward_points": { "data": null }
    }
  }
}

Step 2: Update Profile (Name, Date of Birth)

Update the user's name and date of birth. The date_of_birth field accepts a Unix timestamp in milliseconds.

PUT /api/v1/users/me

cURL

curl -X PUT "$BASE_URL/api/v1/users/me" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "type": "users",
      "attributes": {
        "first_name": "Jane",
        "last_name": "Smith",
        "date_of_birth": 632188800000,
        "marketing_email_opt_in": true,
        "customer_type": "recreational"
      }
    }
  }'

JavaScript

const updateRes = await fetch(`${BASE_URL}/api/v1/users/me`, {
  method: "PUT",
  headers,
  body: JSON.stringify({
    data: {
      type: "users",
      attributes: {
        first_name: "Jane",
        last_name: "Smith",
        date_of_birth: new Date("1990-01-15").getTime(), // 632188800000
        marketing_email_opt_in: true,
        customer_type: "recreational",
      },
    },
  }),
});

const { data: updatedUser } = await updateRes.json();
console.log(`Updated: ${updatedUser.attributes.first_name} ${updatedUser.attributes.last_name}`);

Response

Returns the full user object with the updated fields.

Common Errors

  • name_and_dob_update_not_alowed (400) — Name or date of birth updates are locked after identity verification.
  • age_not_allowed (400) — Date of birth doesn't meet the store's minimum age requirement.
  • dob_is_required (400) — Date of birth is required but was not provided.
  • locked_verified_user_uploads (400) — User's identity is verified — ID/medical info updates are locked.

Step 3: Update Billing Address

Set or update the billing address used for payment processing.

PATCH /api/v1/users/me/billing/

cURL

curl -X PATCH "$BASE_URL/api/v1/users/me/billing/" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "type": "billing",
      "attributes": {
        "address": {
          "address": "456 Billing Ave",
          "city": "Los Angeles",
          "state": "CA",
          "zip_code": "90002"
        }
      }
    }
  }'

JavaScript

const billingRes = await fetch(`${BASE_URL}/api/v1/users/me/billing/`, {
  method: "PATCH",
  headers,
  body: JSON.stringify({
    data: {
      type: "billing",
      attributes: {
        address: {
          address: "456 Billing Ave",
          city: "Los Angeles",
          state: "CA",
          zip_code: "90002",
        },
      },
    },
  }),
});

const { data: billing } = await billingRes.json();
console.log(`Billing address: ${billing.attributes.address.address}`);
console.log(
  `Use delivery as billing: ${billing.attributes.use_delivery_address_in_billing}`
);

Response

{
  "data": {
    "id": "",
    "type": "billing",
    "attributes": {
      "address": {
        "address": "456 Billing Ave",
        "city": "Los Angeles",
        "state": "CA",
        "zip_code": "90002"
      },
      "use_delivery_address_in_billing": false
    }
  }
}

You can also read the current billing address with GET /api/v1/users/me/billing/.


Step 4: Check Loyalty Points

Check the user's loyalty points balance and tier. Use v3 for the enriched response that includes tier information.

GET /api/v3/users/me/loyalty

cURL

curl -X GET "$BASE_URL/api/v3/users/me/loyalty" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN"

JavaScript

const loyaltyRes = await fetch(`${BASE_URL}/api/v3/users/me/loyalty`, {
  headers,
});

const { data: loyalty } = await loyaltyRes.json();
console.log(`Points: ${loyalty.attributes.points}`);
console.log(`Tier: ${loyalty.attributes.tier}`);

Response

{
  "data": {
    "id": "",
    "type": "loyalties",
    "attributes": {
      "points": "150.00",
      "tier": "Gold"
    }
  }
}

Note: If the store has no loyalty provider configured, this returns error code no_loyalty (400).


Step 5: View Available Rewards

Retrieve loyalty rewards available to the authenticated user. These can be applied to the cart at checkout.

GET /api/v1/users/me/rewards

cURL

curl -X GET "$BASE_URL/api/v1/users/me/rewards" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN"

JavaScript

const rewardsRes = await fetch(`${BASE_URL}/api/v1/users/me/rewards`, {
  headers,
});

const { data: rewards } = await rewardsRes.json();
console.log(`${rewards.length} rewards available:`);
rewards.forEach((r) => {
  console.log(
    `  ${r.attributes.name}${r.attributes.points_required} points (${r.attributes.discount_type})`
  );
});

Response

{
  "data": [
    {
      "id": "42",
      "type": "rewards",
      "attributes": {
        "name": "$5 Off Next Purchase",
        "description": "Get $5 off any order over $25",
        "points_required": 100,
        "is_stackable": false,
        "source": "blaze",
        "discount_amount": "5.00",
        "discount_type": "dollar",
        "reward_good": null
      }
    },
    {
      "id": "43",
      "type": "rewards",
      "attributes": {
        "name": "Free Preroll",
        "description": "Redeem for a free house preroll",
        "points_required": 200,
        "is_stackable": false,
        "source": "blaze",
        "discount_amount": "",
        "discount_type": "product",
        "reward_good": {
          "name": "House Preroll",
          "product_id": "prod-abc-123"
        }
      }
    }
  ]
}

Tip: For store-level rewards visible to all users (no auth required), use GET /api/v1/store/deals/rewards.


Step 6: Apply a Reward to the Cart

Apply a reward to an existing cart via the cart update endpoint. The reward_id field references a reward from Step 5.

PUT /api/v5/carts/{cart_uuid}

cURL

curl -X PUT "$BASE_URL/api/v5/carts/CART_UUID" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "id": "CART_UUID",
      "type": "carts",
      "attributes": {
        "reward_id": "42",
        "promo_codes": []
      }
    }
  }'

JavaScript

const cartId = "CART_UUID"; // from a previous cart creation
const selectedReward = rewards[0]; // "$5 Off Next Purchase"

const applyRewardRes = await fetch(`${BASE_URL}/api/v5/carts/${cartId}`, {
  method: "PUT",
  headers,
  body: JSON.stringify({
    data: {
      id: cartId,
      type: "carts",
      attributes: {
        reward_id: selectedReward.id,
        promo_codes: [],
      },
    },
  }),
});

const { data: cartWithReward } = await applyRewardRes.json();
console.log(`Reward applied: ${selectedReward.attributes.name}`);
console.log(`Cart total after reward: $${cartWithReward.attributes.total}`);

Response

{
  "data": {
    "id": "cart-uuid",
    "type": "carts",
    "attributes": {
      "subtotal": 90.00,
      "total": 93.33,
      "tax": 8.33,
      "reward_id": "42",
      "promo_codes": [],
      "items": [ ... ]
    }
  }
}

Note: Rewards and promo codes may not always be stackable. Check the is_stackable field on the reward to determine if it can be combined with promo codes.


Step 7: Check Identity Verification Status

Some stores require identity verification before allowing purchases. Check the current user's verification status.

GET /api/v1/users/me/identity-verification/

cURL

curl -X GET "$BASE_URL/api/v1/users/me/identity-verification/" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN"

JavaScript

const verifyRes = await fetch(
  `${BASE_URL}/api/v1/users/me/identity-verification/`,
  { headers }
);

const { data: verification } = await verifyRes.json();
console.log(`Service: ${verification.attributes.service}`);
console.log(`Verified: ${verification.attributes.is_verified}`);
console.log(`Has driver's license: ${verification.attributes.has_drivers_license}`);
console.log(`Can see menu: ${verification.attributes.can_see_menu}`);

if (!verification.attributes.is_verified) {
  console.log("User needs to complete identity verification");
  // Start a verification transaction:
  // POST /api/v1/users/me/identity-verification/{service}
}

Response

{
  "data": {
    "id": "berbix-delivery",
    "type": "identity_verification_report",
    "attributes": {
      "service": "berbix",
      "delivery_type": "delivery",
      "is_verified": true,
      "has_drivers_license": true,
      "has_selfie_id": true,
      "verified_by": "berbix",
      "can_see_menu": true
    }
  }
}

If the user is not verified and the store requires it, start a verification transaction with POST /api/v1/users/me/identity-verification/{service} (e.g., berbix).


Complete Flow Summary

GET   /api/v1/users/me                       → Get user profile
PUT   /api/v1/users/me                       → Update profile (name, DOB, preferences)
PATCH /api/v1/users/me/billing/              → Update billing address
GET   /api/v3/users/me/loyalty               → Check loyalty points and tier
GET   /api/v1/users/me/rewards               → View available rewards
PUT   /api/v5/carts/{cart_uuid}              → Apply reward to cart
GET   /api/v1/users/me/identity-verification/ → Check identity verification status

What's Next?