Skip to main content

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.

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 internal org identifier
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.

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. This makes it easy to correlate Sticker data with your system.
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