navigation hamburger icon
Trolley Logo

API Documentation

Table of Contents

curl Ruby Python Javascript PHP C# Java

Partner API Introduction

The Partner API allows support for sub-merchant accounts, connected to a parent Merchant account.

If your business is a software platform that has multiple business customers that require specific or unique settings for each, such as white-label branding in your customer’s brand, or US tax form settings, etc, our Partner API may be suitable to use to achieve this.

Create Sub-merchant

This endpoint is for creating a new sub-merchant. The new sub-merchant is bound to the parent merchant used to create it. This endpoint requires that the Partner API (Sub-merchant feature) be enabled for your merchant account. Contact support for more information.

Example Request

curl \
-H "Authorization: prsign ${PARENT_TROLLEY_ACCESS_KEY}:${PARENT_TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X POST 'https://api.trolley.com/v1/profile/submerchant' \
-d '{
  "merchant": {
    "name": "Acme Sandbox Merchant",
    "currency": "USD",
    "country": "US",
    "website": "https://example.com"
  },
  "onboarding": {
    "businessLegalName": "Acme Sandbox Merchant LLC",
    "businessAsName": "Acme Sandbox Merchant",
    "businessTaxId": "12-3456789",
    "businessPhone": "+14165551212",
    "businessWebsite": "https://example.com",
    "businessCategory": "business_service",
    "businessCountry": "US",
    "businessCity": "New York",
    "businessAddress": "123 Example Street",
    "businessZip": "10001",
    "businessRegion": "NY",
    "businessTotalMonthly": "10000",
    "businessPpm": "100",
    "businessIntlPercentage": "25",
    "expectedPayoutCountries": "US,CA"
  }
}'

Request Schema

{
  // required data:
  merchant: {
    name: string; // Sub-merchants business name
    currency: string; // 3 letter currency code in ISO 4217
  };

  // also required
  onboarding: {
    businessWebsite: string;
    businessLegalName: string;
    businessAsName: string;
    businessTaxId: string;  
    businessCategory: string;
    businessCountry: string; // 2 letter country ISO 3166-1 alpha-2
    businessCity: string;
    businessAddress: string;
    businessZip: string; // optional if country has postal code
    businessRegion: string; // state or province - ideally 2 letter code
    businessTotalMonthly: string; // Expected total value of payouts per month in USD (e.g. "10000" or "500000" etc)
    businessPpm: string; // Expected number of payouts per month; (e.g. "15000" or "520000" etc).
    businessIntlPercentage: string; // The percentage (%) of payment volume that will be sent internationally; (e.g. "15" or "52" etc).
    expectedPayoutCountries: string // 2 letter country ISO 3166-1 alpha-2. Accepts multiple country input
  };
}

Response (200 Ok)

{
  "ok": true,
  "merchant": {
    "id": "M-1a2B3c4D5e6F7g8H9i0J1k",
    "accessKey": "AK-1a2B3c4D5e6F7g8H9i0J1k",
    "secretKey": "SK-1a2B3c4D5e6F7g8H9i0J1k"
  }
}

Response Schema

{
  ok: boolean;
  merchant: {
    id: string;
    accessKey: string;
    secretKey: string;
  }
}

This endpoint will return a sub-merchant id (alphanumeric guid) and an API key. The API key is important if you’re going to access the sub-merchant programmatically as this is the only time you will be able to get it - so make sure you store it in the right place.

HTTP Request

POST /v1/profile/submerchant

Fields Description
merchant.name
required
string
Name of the sub-merchant
merchant.website
required
string
Website URL
merchant.country
required
string
2 letter country code in ISO 3166-1
merchant.currency
required
string
3 letter currency code in ISO 4217
onboarding.businessLegalName
required
string
Legal name of the sub-merchant
onboarding.businessAsName
required
string
Doing business name of the sub-merchant
onboarding.businessTaxId
required
string
Tax ID of the sub-merchant
onboarding.businessPhone
required
string
Phone number
onboarding.businessWebsite
required
string
Website URL
onboarding.businessCategory
required
string
The category of the business. Expected one of the allowed values, as defined below.
onboarding.businessCountry
required
string
2 letter country code in ISO-3166-1
onboarding.businessCity
required
string
City of the sub-merchant
onboarding.businessAddress
required
string
Address of the sub-merchant
onboarding.businessZip
required
string
Postal code for the sub-merchant
onboarding.businessRegion
required
string
Region of the sub-merchant (e.g. state/province)
onboarding.businessTotalMonthly
required
string
Expected total value of payouts per month in USD (e.g. “10000” or “500000” etc).
onboarding.businessPpm
required
string
Expected number of payouts per month; (e.g. “15000” or “520000” etc).
onboarding.businessIntlPercentage
required
string
The percentage (%) of payment volume that will be sent internationally; (e.g. “15” or “52” etc).
onboarding.expectedPayoutCountries
required
string
Expected countries the sub-merchant will payout to

If any of the required “onboarding” fields are missing then onboarding will not be complete. Following are more details about accepted parameters for some of the required attributes as defined above.

Allowed Values for Business Category

Category Allowed Value
Online Market online_market
App Store app_store
Affiliate Platform affiliate_platform
Ad Network ad_network
Crowd Funding crowdfunding
Crowd Sourcing crowdsourcing
Share Economy share_economy
E-Commerce e-commerce
Charity charity
Surveys surveys
Rebates rebates
Startup startup
Publishing publishing
Entertainment entertainment
Travel travel
Education education
Manufacturing manufacturing
Business Service business_service
Influencer Platform influencer_platform
Online Gambling online_gambling
Adult Entertainment adult_entertainment
Multi Level Marketing multi_level_marketing
Firearms firearms
Money Transmitter Service money_transmitter_service
Credit Card Processing credit_card_processing
Other other

This endpoint will return a sub-merchant id (alphanumeric guid) and an API key. The API key is important if you’re going to access the sub-merchant programmatically as this is the only time you will be able to get it - so make sure you store it in the right place.

HTTP Code Description
200 Submerchant successfully created
401 Invalid API key
404 Recipient not found
500 Internal error

Errors

This table lists the expected errors that this method could return. However, other errors can be returned in the case where the service is down or other unexpected factors affect processing. Callers should always check the value of the ok params in the response.

Error Code Description
not_found Object doesn’t exist
invalid_api_key Invalid API key
internal_server_error Internal server errors

Modify Onboarding Information

With a sub-merchant’s key, you can modify onboarding information for an existing sub-merchant. You need to be using the sub-merchant’s key.

HTTP Request

POST https://api.trolley.com/v1/onboarding/update

Example Request

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X POST 'https://api.trolley.com/v1/onboarding/update' \
-d '{
  "businessTotalMonthly": "10000",
  "businessPpm": "100"
}'

Request Schema

{
businessTotalMonthly?: string; // should be a number of USD (eg: "10000" or "500000" etc..)
businessPpm?: string
}

Response (200 Ok)

{
  "ok": true
}

Response Schema

{
  ok: boolean;
}

Request

Fields Description
businessTotalMonthly
optional
string
Expected total value of payouts per month in USD (e.g. “10000” or “500000” etc), expressed as a JSON string
businessPpm
optional
string
Number of expected payments per month.
HTTP Code Description
200 Submerchant successfully created
401 Invalid API key
404 Recipient not found
500 Internal error

Errors

This table lists the expected errors that this method could return. However, other errors can be returned in the case where the service is down or other unexpected factors affect processing. Callers should always check the value of the ok params in the response.

Error Code Description
not_found Object doesn’t exist
invalid_api_key Invalid API key
internal_server_error Internal server errors

Get Funding Information

Example Request

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X GET 'https://api.trolley.com/v1/balances/info'

Response (200 Ok)

{
  "ok": true,
  "info": [
    {
      "accountAddress": "100 King St W",
      "accountCity": "Toronto",
      "accountCountryCode": "CA",
      "accountCurrency": "USD",
      "accountName": "Trolley Funding Account",
      "accountNum": "*****1234",
      "accountPostalCode": "M5X1C9",
      "accountRegion": "ON",
      "bankAddress": "100 King St W",
      "bankCity": "Toronto",
      "bankCountry": "Canada",
      "bankCountryCode": "CA",
      "bankName": "Example Bank",
      "bankPostalCode": "M5X1C9",
      "bankRegion": "ON",
      "institution": "001",
      "referenceMemo": "merchant-reference-123",
      "routingNumber": "021000021"
    }
  ]
}

Response Schema

{
  info: {
    accountAddress: string;
    accountCity: string;
    accountCountryCode: string;
    accountCurrency: string;
    accountName: string;
    accountNum: string;
    accountPostalCode: string;
    accountRegion: string;
    bankAddress: string;
    bankCity: string;
    bankCountry: string;
    bankCountryCode: string;
    bankName: string;
    bankPostalCode: string;
    bankRegion: string;
    institution: string;
    // IMPORTANT: must be put in the memo field
    referenceMemo: string;
    routingNumber: string;
    // potentially other fields depending on the bank
  }[],
}

HTTP Request

GET https://api.trolley.com/v1/balances/info

Returns the bank account information needed in order to fund the sub-merchant account by bank wire or bank transfer. Note that the referenceMemo information must be included in the memo field of the bank wire or bank transfer. This is used to route the the incoming funds to the correct sub-merchant account balance.

HTTP Code Description
200 Funding information returned
401 Invalid API key
500 Internal error

Errors

Error Code Description
invalid_api_key Invalid API key
internal_server_error Internal server errors

Sandbox Merchant

Sandbox Create

This endpoint works identically to the “create sub-merchant” endpoint but creates sandbox sub-merchants instead.

This endpoint is for creating a new sub-merchant. The new sub-merchant is bound to the parent sandbox merchant used to create it. This endpoint requires that the sub-merchant feature be enabled for your merchant.

Request

curl \
-H "Authorization: prsign ${PARENT_TROLLEY_ACCESS_KEY}:${PARENT_TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X POST 'https://api.trolley.com/v1/profile/sandbox' \
-d '{
  "apikey": true,
  "merchant": {
    "name": "Docs Sandbox Submerchant",
    "currency": "USD"
  }
}'

Request Schema

{
  // optional - true to generate API keys for the sandbox account
  apikey: boolean;
  // optional data -- copied from master merchant if not provided
  merchant: {
    name: string; // Sub-merchants business name
    currency: string; // 3 letter currency code in ISO 4217
  };
}

This endpoint will return a sub-merchant id (alphanumeric guid) and an API key. The API key is important if you’re going to access the sub-merchant programmatically as this is the only time you will be able to get it to make sure you store it in the right place.

Response (200 Ok)

{
  "ok": true,
  "merchant": {
    "id": "M-1a2B3c4D5e6F7g8H9i0J1k",
    "accessKey": "AK-1a2B3c4D5e6F7g8H9i0J1k",
    "secretKey": "SK-1a2B3c4D5e6F7g8H9i0J1k"
  }
}

Response Schema

{
  ok: boolean; // true if everything is good
  merchant: {
    id: string;
    accessKey: string; // present if apikey is provided
    secretKey: string; // present if apikey is provided
  }
}

HTTP Request

POST /v1/profile/sandbox

Fields Description
apikey
required
boolean
Value of true to generate API keys for the sandbox account
merchant.name
required
string
Sub-merchant business name
merchant.currency
required
string
3 letter currency code in ISO 4217
HTTP Code Description
200 Submerchant successfully created
401 Invalid API key
403 Invalid parameter
500 Internal error

Errors

Error Code Description
invalid_field Invalid field value
invalid_api_key Invalid API key
internal_server_error Internal server errors

Sandbox Delete

To delete a sandbox sub merchant that you’ve created you need to provide the id of the sub-merchant to delete.

DELETE /v1/profile/sandbox

Request

curl \
-H "Authorization: prsign ${PARENT_TROLLEY_ACCESS_KEY}:${PARENT_TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X DELETE 'https://api.trolley.com/v1/profile/sandbox' \
-d '{
  "id": "M-1a2B3c4D5e6F7g8H9i0J1k"
}'

Request Schema

{
  // required -- the sandbox id to delete
  id: string;
}

Response (200 Ok)

{
  "ok": true
}

Response Schema

{
  ok: boolean;
}
Fields Description
id
required
string
Id of sandbox sub-merchant to delete
HTTP Code Description
200 Submerchant successfully created
403 Invalid parameter
401 Invalid API key
500 Internal error

Errors

This table lists the expected errors that this method could return. However, other errors can be returned in the case where the service is down or other unexpected factors affect processing. Callers should always check the value of the ok params in the response.

Error Code Description
not_found Object doesn’t exist
invalid_api_key Invalid API key
internal_server_error Internal server errors
invalid_field

Widget Configuration

Example Request

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X POST 'https://api.trolley.com/v1/iframe/config' \
-d '{
  "colors": {
    "primary": "#112233",
    "success": "#22AA66",
    "error": "#CC3344",
    "warning": "#CC9900",
    "border": "#CCCCCC",
    "heading": "#111111",
    "text": "#222222",
    "inputText": "#222222",
    "inputBorder": "#DDDDDD",
    "subText": "#666666",
    "background": "#FFFFFF"
  }
}'

Request Schema

HexColor = string

// regex: “/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i”
// eg: “#112233” or “112233” or “abFF22” or “#123” etc..

{
  colors:  {
    primary: HexColor;
    success: HexColor;
    error: HexColor;
    warning: HexColor;
    border: HexColor;
    heading: HexColor;
    text: HexColor;
    inputText: HexColor;
    inputBorder: HexColor;
    subText: HexColor;
    background: HexColor;
  },
},

Response (200 Ok)

{
  "ok": true
}

HTTP Request

POST https://api.trolley.com/v1/iframe/config

You can implement the Recipient Widget for sub-merchant accounts in order to capture recipient information directly into each sub-merchant account. Ensure you use the relevant sub-merchant API key when you integrate the widget.

This endpoint allows you to programmatically customimze the colors of the widget for each sub-merchant.

Fields Description
colors.primary
required
string
Primary color
colors.success
required
string
Success state color
colors.error
required
string
Error state color
colors.warning
required
string
Warning state color
colors.border
required
string
Border color
colors.heading
required
string
Heading color
colors.text
required
string
Body text color
colors.inputText
required
string
Input text color
colors.inputBorder
required
string
Input border color
colors.subText
required
string
Secondary text color
colors.background
required
string
Background color
HTTP Code Description
200 Widget config updated
401 Invalid API key
500 Internal error

Errors

Error Code Description
invalid_api_key Invalid API key
internal_server_error Internal server errors

Webhooks

Create Webhook

HTTP Request

POST https://api.trolley.com/v1/subscriptions

Adds a new webhook

Example Request

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X POST 'https://api.trolley.com/v1/subscriptions' \
-d '{
  "action": "created",
  "model": "recipient",
  "target": "https://example.com/webhooks/trolley"
}'

Request Schema

{
  action: NotificationAction,
  model: NotificationType,
  target: string, // URL endpoint to send events to
}

Enumerated Strings

enum NotificationAction {
  CREATED = "created",
  UPDATED = "updated",
  DELETED = "deleted",

  // Batch
  PROCESSING = "processing", // fired when batch startProcessing() is called
  COMPLETED = "completed", // processed with at least one success
  // We don't expose Batch.COMPLETED in the UI because
  // It overlaps with PROCESSING too much

  // Payment
  FAILED = "failed",
  RETURNED = "returned",

  // Batch and Payments
  PROCESSED = "processed", // once a batch/payment is processed successfully
  // (for batch this means one payment is successful)

  // User
  PASSWORD_RESET = "password-reset",

  // Recipient
  COMPLIANCE_CHECK = "compliance-check",

  // Batch and Recipient uploads
  UPLOAD_RECEIVED = "upload-received",
  UPLOAD_PROCESSING = "upload-processing",
  UPLOAD_COMPLETE = "upload-completed",

  ALL = "*",
}

enum NotificationType {
  USER = "user",
  RECIPIENT = "recipient",
  UPLOAD = "upload",
  BATCH = "batch",
  PAYMENT = "payment",
  RECIPIENT_ACCOUNT = "recipientAccount",
  ALL = "*",
}

Response (200 Ok)

{
  "ok": true,
  "subscription": {
    "id": "S-1a2B3c4D5e6F7g8H9i0J1k",
    "action": "created",
    "model": "recipient",
    "target": "https://example.com/webhooks/trolley"
  }
}

Response Schema

{
  ok: boolean; 
  subscription: {
    id: string;
    action: NotificationAction;
    model: NotificationType;
    target: string;
  }
}

Request

Fields Description
action
required
string
The event that triggered this webhook
model
required
string
NotificationType - description of the model object
target
required
string
URL to send webhooks to
HTTP Code Description
200 Webhook created
401 Invalid API key
500 Internal error

Errors

Error Code Description
invalid_api_key Invalid API key
invalid_field Invalid field value
internal_server_error Internal server errors

Webhooks List

HTTP Request

GET https://api.trolley.com/v1/subscriptions

Get the list of subscriptions and values

Example Request

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X GET 'https://api.trolley.com/v1/subscriptions'

Response (200 ok)

{
  "ok": true,
  "subscriptions": [
    {
      "id": "S-1a2B3c4D5e6F7g8H9i0J1k",
      "action": "created",
      "model": "recipient",
      "target": "https://example.com/webhooks/trolley"
    }
  ]
}

Response Schema

{
  subscriptions: {
    id: string,
    action: NotificationAction,
    model: NotificationType,
    target: string,
  }[];
}
HTTP Code Description
200 Webhooks returned
401 Invalid API key
500 Internal error

Errors

Error Code Description
invalid_api_key Invalid API key
internal_server_error Internal server errors

Get, Update, and Delete Webhook

HTTP Request

GET https://api.trolley.com/v1/subscriptions/:id

PATCH https://api.trolley.com/v1/subscriptions/:id

DELETE https://api.trolley.com/v1/subscriptions/:id

Example Request (GET)

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X GET 'https://api.trolley.com/v1/subscriptions/S-1a2B3c4D5e6F7g8H9i0J1k'

Response (200 Ok)

{
  "ok": true,
  "subscription": {
    "id": "S-1a2B3c4D5e6F7g8H9i0J1k",
    "action": "created",
    "model": "recipient",
    "target": "https://example.com/webhooks/trolley"
  }
}

Example Request (PATCH)

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X PATCH 'https://api.trolley.com/v1/subscriptions/S-1a2B3c4D5e6F7g8H9i0J1k' \
-d '{
  "action": "updated",
  "model": "recipient",
  "target": "https://example.com/webhooks/trolley-updated"
}'

Response (200 Ok)

{
  "ok": true,
  "subscription": {
    "id": "S-1a2B3c4D5e6F7g8H9i0J1k",
    "action": "updated",
    "model": "recipient",
    "target": "https://example.com/webhooks/trolley-updated"
  }
}

Example Request (DELETE)

curl \
-H "Authorization: prsign ${TROLLEY_ACCESS_KEY}:${TROLLEY_SIGNATURE:-docs-signature}" \
-H 'Content-Type: application/json' \
-H "X-PR-Timestamp: ${TROLLEY_TIMESTAMP:-$(date +%s)}" \
-X DELETE 'https://api.trolley.com/v1/subscriptions/S-1a2B3c4D5e6F7g8H9i0J1k'

Response (200 Ok)

{
  "ok": true
}
Fields Description
id
required
string
Webhook subscription ID used in the path
action
optional
string
Event action filter for PATCH
model
optional
string
Event model filter for PATCH
target
optional
string
Destination URL for PATCH
HTTP Code Description
200 Webhook operation passed
401 Invalid API key
404 Webhook not found
500 Internal error

Errors

Error Code Description
invalid_api_key Invalid API key
not_found Object doesn’t exist
internal_server_error Internal server errors

Webhook callbacks for Sub-merchant profiles

The format for all webhook callbacks are the same except for the model object returned. Webhook callbacks and their format are explained here:

http://developers.trolley.com/api/#webhooks

Merchant Model Object:

interface Merchant {
  id: number;
  merchantId: string;
  name: string;
  parentMerchantId: string | null;
  status: string;
  phone: string;
  website: string;
  sandbox: boolean;
  primaryCurrency: extra.CurrencyCode; // string 3 letters
  allowedIPs: string;
  allowedDomains: string;
  country: extra.CountryCode | null; // string 3 letters
  region: string | null;
}

The “status” field will tell you if the sub-merchant has gone live. The sub-merchant status values can be one of these:

Once the sub-merchant or merchant is “approved” that merchant is live.

enum MerchantStatus {
 APPROVED = "approved",
 APPROVED_BY_PARTNER = "approved_by_partner",
 SUSPENDED = "suspended",
 DELETED = "deleted",
 PENDING = "pending",
 SIGNUP_REQUESTED = "signup_requested",
}
×