Skip to main content

Documentation Index

Fetch the complete documentation index at: https://embed.usesticker.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Organization Setup endpoint is your one-stop shop for provisioning customer data in Sticker. Call it when a customer enables procurement in your platform—it creates the organization, user profile, shipping locations, and even sets up billing with Stripe.

Data Model: Organizations and Profiles

Sticker models organizations and profiles as a many-to-one relationship:
  • Organization: the business, company, practice, store, school, or legal entity buying supplies.
  • Profile: an employee or user who belongs to that business.
  • Relationship: many profiles can belong to one organization, but each distinct business should have its own organization.
Your backend should map to the same structure when you call Sticker:
Acme Cleaning LLC             internalOrgId = acme-cleaning
  - Jane Smith                internalUserId = user-123
  - John Doe                  internalUserId = user-456

Bright Star Janitorial Inc.   internalOrgId = bright-star-janitorial
  - Maria Lopez               internalUserId = user-789
Do not reuse one generic internalOrgId for multiple unrelated businesses. Sticker treats internalOrgId as the unique identifier for a business organization. If multiple companies share the same internalOrgId, their users will be grouped into the same Sticker organization and will share org-level data such as shipping locations, payment methods, catalog, and billing context.
If a business has only one user, it still needs its own unique internalOrgId. Additional employees from the same business should reuse that same internalOrgId and use their own unique internalUserId.

When to Call This Endpoint

1

User Enables Procurement

A customer clicks “Enable Supplies” (or similar) in your platform
2

Gather Required Data

Collect the user’s info and at least one shipping location
3

Call Setup Endpoint

Send data to Sticker’s /v1/organizations/setup endpoint
4

Store the Profile ID

Save the returned profile.id for future handshake requests

What Gets Created

When you call the setup endpoint, Sticker automatically:
  1. Creates a Stripe Customer - For billing and payment method storage
  2. Creates the Organization - Linked to your internalOrgId
  3. Creates Shipping Locations - For order delivery
  4. Creates an Auth User - For secure authentication
  5. Creates a User Profile - Linked to the org and auth user

API Endpoint

POST /v1/organizations/setup
Base URL: https://api.usesticker.com

Authentication

Include your Partner API Key in the Authorization header:
Authorization: Bearer sk_live_your_api_key_here

Request Format

{
  "internalOrgId": "org-12345",
  "organizationName": "Acme Medical Practice",
  
  "internalUserId": "user-789",
  "user": {
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@acmemedical.com",
    "phoneNumber": "+1-555-0100"
  },
  
  "shippingLocations": [
    {
      "internalShippingLocationId": "loc-001",
      "name": "Main Office",
      "nickname": "HQ",
      "address": {
        "line1": "123 Medical Plaza",
        "line2": "Suite 200",
        "city": "San Francisco",
        "province": "CA",
        "postalCode": "94102"
      },
      "contact": {
        "name": "Reception Desk",
        "phone": "+1-555-0101",
        "email": "office@acmemedical.com"
      },
      "isDefault": true,
      "deliveryInstructions": "Ring bell at front desk"
    }
  ],
  
  "billingAddress": {
    "line1": "123 Medical Plaza",
    "city": "San Francisco",
    "province": "California",
    "postalCode": "94102"
  },
  "organizationEmail": "billing@acmemedical.com",
  "organizationPhone": "+1-555-0100"
}

Request Parameters

Required Fields

FieldTypeDescription
internalOrgIdstringYour unique identifier for the business organization. Do not reuse this across unrelated businesses.
organizationNamestringDisplay name for the organization
internalUserIdstringYour internal user identifier
user.firstNamestringUser’s first name
user.lastNamestringUser’s last name
user.emailstringUser’s email (must be valid format)

Optional Fields

FieldTypeDescription
user.phoneNumberstringUser’s phone number
userAddressobjectUser’s personal address
shippingLocationsarrayOrganization’s shipping locations
billingAddressobjectOrganization’s billing address
organizationEmailstringOrganization’s contact email
organizationPhonestringOrganization’s phone number

Address Object

FieldTypeRequiredDescription
line1stringYesStreet address
line2stringNoApt/Suite/Unit
citystringYesCity
provincestringYesState (e.g., “CA” or “California”)
postalCodestringYesZIP code
countrystringNoDefaults to “United States”
State Normalization: The API accepts both abbreviations (“CA”) and full names (“California”). Internally, all values are stored as full state names.

Shipping Location Object

FieldTypeRequiredDescription
internalShippingLocationIdstringYesYour internal location ID
namestringYesLocation name (e.g., “Main Office”)
nicknamestringNoShort nickname
addressobjectYesAddress object (see above)
contact.namestringNoContact person name
contact.phonestringNoContact phone
contact.emailstringNoContact email
isDefaultbooleanNoIs this the default location?
deliveryInstructionsstringNoNotes for delivery drivers

Response Format

Success (200 OK)

{
  "success": true,
  "data": {
    "organization": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Medical Practice",
      "internalOrgId": "org-12345",
      "stripeCustomerId": "cus_xxxxxxxxxxxxx"
    },
    "profile": {
      "id": "660f9500-f30c-52e5-b827-557766551111",
      "partner": "770a0600-...",
      "organization": "550e8400-...",
      "internal_user_id": "user-789",
      "user": "880b1700-...",
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane@acmemedical.com",
      "created_at": "2024-01-15T10:30:00.000Z"
    },
    "shippingLocations": [
      {
        "id": "990c2800-...",
        "name": "Main Office",
        "nickname": "HQ",
        "internalShippingLocationId": "loc-001",
        "address": {
          "line1": "123 Medical Plaza",
          "line2": "Suite 200",
          "city": "San Francisco",
          "province": "California",
          "postalCode": "94102",
          "country": "United States"
        },
        "isDefault": true,
        "isActive": true
      }
    ],
    "isNewOrganization": true
  }
}

Key Response Fields

FieldDescription
organization.idSticker’s UUID for the org (store this if needed)
organization.stripeCustomerIdStripe customer for billing
profile.idUser profile UUID (use in handshake if needed)
profile.internal_user_idYour internal user ID (echoed back)
isNewOrganizationtrue if org was created, false if user was added to existing

Adding Users to Existing Organizations

Call the same endpoint with the same internalOrgId but a different internalUserId:
{
  "internalOrgId": "org-12345",
  "organizationName": "Acme Medical Practice",
  
  "internalUserId": "user-456",
  "user": {
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@acmemedical.com"
  }
}
The response will have isNewOrganization: false, and the new user will have access to the existing organization’s shipping locations and shared payment methods.

Common Mapping Mistake

Do not model every customer under one shared organization ID:
// Incorrect: two unrelated companies share the same internalOrgId
[
  {
    "internalOrgId": "suppliesShop",
    "organizationName": "Acme Cleaning LLC",
    "internalUserId": "acme-user-1"
  },
  {
    "internalOrgId": "suppliesShop",
    "organizationName": "Bright Star Janitorial Inc.",
    "internalUserId": "bright-star-user-1"
  }
]
Use a unique organization ID for each business:
// Correct: each business has its own internalOrgId
[
  {
    "internalOrgId": "acme-cleaning",
    "organizationName": "Acme Cleaning LLC",
    "internalUserId": "acme-user-1"
  },
  {
    "internalOrgId": "bright-star-janitorial",
    "organizationName": "Bright Star Janitorial Inc.",
    "internalUserId": "bright-star-user-1"
  }
]

Error Handling

{
  "error": "Validation Error",
  "message": "Invalid request body",
  "code": "VALIDATION_ERROR",
  "details": [
    {
      "code": "invalid_string",
      "message": "State must be a valid US state",
      "path": ["shippingLocations", 0, "address", "province"]
    }
  ]
}
Common causes:
  • Invalid email format
  • Invalid state/province (must be valid US state)
  • Missing required fields
{
  "error": "Unauthorized",
  "message": "Invalid or missing API key"
}
Solution: Check Authorization: Bearer {key} header
{
  "error": "Conflict",
  "message": "User already exists in this organization",
  "code": "USER_ALREADY_EXISTS",
  "data": {
    "profileId": "660f9500-...",
    "email": "jane@acmemedical.com"
  }
}
Solution: User is already set up. Use the returned profileId for handshake.

Code Examples

async function setupOrganization(org, user, locations) {
  const response = await fetch('https://api.usesticker.com/v1/organizations/setup', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.STICKER_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      internalOrgId: org.id,
      organizationName: org.name,
      internalUserId: user.id,
      user: {
        firstName: user.firstName,
        lastName: user.lastName,
        email: user.email,
        phoneNumber: user.phone
      },
      shippingLocations: locations.map(loc => ({
        internalShippingLocationId: loc.id,
        name: loc.name,
        address: {
          line1: loc.street,
          city: loc.city,
          province: loc.state,
          postalCode: loc.zip
        },
        isDefault: loc.isPrimary
      }))
    })
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Setup failed: ${error.message}`);
  }

  const result = await response.json();
  
  // Store the profile ID in your database
  await db.users.update(user.id, {
    stickerProfileId: result.data.profile.id
  });
  
  return result;
}

Best Practices

Always use your own internal IDs for internalOrgId, internalUserId, and internalShippingLocationId. internalOrgId must uniquely identify the customer business, while internalUserId must uniquely identify a user or employee.
Use the same internalOrgId only for users who belong to the same business. Use a different internalOrgId for every distinct customer business, even if that business currently has only one user.
Always include at least one shipping location when creating a new organization. This ensures users can complete checkout immediately.
If you get a 409 (User Already Exists), don’t treat it as an error—the user is already set up! Just use the returned profile ID.
Store the returned profile.id in your database. While you can use internal_user_id for handshake, having the profile ID is useful for debugging.

Next Steps

User Handshake

Authenticate users for each session

API Reference

Complete API specification