Important update 1: Email Support is being transitioned to Webforms. Click here for more information.

API: Managing Customers

The Storefront API lets you create and manage customer accounts programmatically without needing to log in to Storefront Manager. This is useful if you have your own platform or control panel and want to automate customer provisioning when users sign up, sync customer records, or build tooling for your support team.


Note: DNS management via the API only works for domains using Storefront's default Shopco nameservers (a.ns.shopco.com, b.ns.shopco.com, c.ns.shopco.com). Domains using custom nameservers manage their own DNS outside of Storefront.


Before you begin

Requirements

  • An active OpenSRS Storefront with API access enabled
  • API credentials (Client ID and Client Secret) generated in Storefront Manager
  • Your OpenSRS account balance above $10 to keep your Storefront active

Customer endpoints

Create a customer

Creates a new customer account under your reseller.

POST /v1/customer

Request fields

FieldTypeRequiredConstraintsDescription
first_namestringYesMax 50 charsCustomer's first name
last_namestringYesMax 50 charsCustomer's last name
emailstringYesValid email formatCustomer's email address
usernamestringYes3–20 chars, [a-zA-Z0-9_-] only, unique per resellerLogin username
address1stringYesMax 255 charsStreet address
citystringYesMax 100 charsCity
statestringYesFull name, max 50 chars (e.g. Ontario)State or province
postal_codestringYesValidated against countryPostal or ZIP code
countrystringYes2-letter ISO 3166-1 alpha-2 code (e.g. CA, US)Country (e.g. CA)
phonestringYesE.164 format, validated against countryPhone number — stored in normalized format (e.g. +1.4165550101)
send_emailbooleanNoDefault: falseSend a welcome email to the customer
currency_codestringNoMust be a supported currency codeCustomer's billing currency (e.g. USD, CAD) — returns 400 if not recognized
external_user_idstringNoMax 255 chars, no control charactersYour internal reference ID for this customer

Notes:

  • postal_code is validated against country at the database level.
  • phone validation is country-aware.

Example request

{
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane.doe@example.com",
  "username": "janedoe01",
  "address1": "123 Main St",
  "city": "Toronto",
  "state": "Ontario",
  "postal_code": "M5V 2T6",
  "country": "CA",
  "phone": "+1 416 555 0101",
  "send_email": false,
  "currency_code": "CAD",
  "external_user_id": "cust-12345"
}

Example cURL

curl -X POST "https://api.shopco.com/v1/customer" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane.doe@example.com",
    "username": "janedoe01",
    "address1": "123 Main St",
    "city": "Toronto",
    "state": "Ontario",
    "postal_code": "M5V 2T6",
    "country": "CA",
    "phone": "+1 416 555 0101",
    "send_email": false,
    "currency_code": "CAD",
    "external_user_id": "cust-12345"
  }'

Success response

200 OK — the new customer's UUID, returned as a JSON string.

"8d9f0ef8-6045-4bb2-b473-f7f5c2dcf0a8"

Get a customer

Returns a single customer by ID.

GET /v1/customer/{customer_id}

Path parameters

ParameterTypeDescription
customer_idUUIDThe customer's ID (returned by create)

Example cURL

curl -X GET "https://api.shopco.com/v1/customer/8d9f0ef8-6045-4bb2-b473-f7f5c2dcf0a8" \
  -H "Authorization: Bearer <access_token>"

Success response

200 OK — a customer object.

FieldTypeDescription
idUUIDCustomer's unique ID
first_namestring or nullFirst name
last_namestring or nullLast name
emailstringEmail address
usernamestringLogin username
statusstringAccount status (active, suspended, etc.)
created_datedatetime or nullISO 8601 timestamp of account creation
last_login_datedatetime or nullISO 8601 timestamp of last login
phonestring or nullPhone number in normalized format
address1string or nullStreet address
address2string or nullAddress line 2
address3string or nullAddress line 3
citystring or nullCity
statestring or nullState or province
postal_codestring or nullPostal or ZIP code
countrystring or null2-letter ISO country code
currencyobject or null{ "code": "USD", "symbol": "$", "descr": "US Dollar" }
totp_enabledbooleanWhether 2FA is enabled on the account
external_user_idstring or nullYour internal reference ID
stripe_customer_idstring or nullStripe customer ID if a payment method is on file

Example response

{
  "id": "8d9f0ef8-6045-4bb2-b473-f7f5c2dcf0a8",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane.doe@example.com",
  "username": "janedoe01",
  "status": "active",
  "created_date": "2026-04-01T10:00:00.000000Z",
  "last_login_date": null,
  "phone": "+1.4165550101",
  "address1": "123 Main St",
  "address2": null,
  "address3": null,
  "city": "Toronto",
  "state": "Ontario",
  "postal_code": "M5V 2T6",
  "country": "CA",
  "currency": {
    "code": "CAD",
    "symbol": "$",
    "descr": "Canadian Dollar"
  },
  "totp_enabled": false,
  "external_user_id": "cust-12345",
  "stripe_customer_id": null
}

Update a customer

Partially updates a customer. Only include the fields you want to change — omitted fields are left unchanged.

PATCH /v1/customer/{customer_id}

Path parameters

ParameterTypeDescription
customer_idUUIDThe customer's ID

Request fields

All fields are optional. At least one must be provided.

FieldTypeConstraintsDescription
first_namestringMax 50 charsFirst name
last_namestringMax 50 charsLast name
emailstringValid email formatEmail address
address1stringMax 255 charsStreet address
citystringMax 100 charsCity
statestring or nullFull name, max 50 chars (e.g. Ontario)State or province
postal_codestring or nullValidated against countryPostal or ZIP code
countrystring2-letter ISO codeCountry
phonestringE.164 format, validated against countryPhone number — if updating, include country in the same request or the existing country on the account is used. Returns 400 if neither is present.
currency_codestringMust be a supported currency codeBilling currency
external_user_idstringMax 255 chars, no control charactersYour internal reference ID

Example request

{
  "city": "Vancouver",
  "state": "British Columbia",
  "external_user_id": "cust-12345-updated"
}

Example cURL

curl -X PATCH "https://api.shopco.com/v1/customer/8d9f0ef8-6045-4bb2-b473-f7f5c2dcf0a8" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "city": "Vancouver",
    "state": "British Columbia",
    "external_user_id": "cust-12345-updated"
  }'

Success response

200 OK — empty body.


Error responses

All error responses follow this structure:

{ "detail": "<message>" }

For field validation errors (Pydantic):

{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "first_name"],
      "msg": "Field required",
      "input": {}
    }
  ]
}

HTTP status codes

StatusMeaning
400 Bad RequestInvalid payload or constraint violation
401 UnauthorizedMissing or invalid token
404 Not FoundCustomer not found
409 ConflictUsername already exists for this reseller
422 Unprocessable EntityField validation failed
429 Too Many RequestsRate limit exceeded — check Retry-After header
500 Internal Server ErrorUnexpected failure — contact support if this persists

Related articles

Questions or issues with the API? Contact OpenSRS Support.

Was this article helpful? If not please submit a request here

How helpful was this article?

Thanks for your feedback!

Do you still need help? If so please submit a request here.