Carbon

Documentation

Welcome to Carbon's docs!

Get Started    

CarbonUSD

Purchase CUSD with USD and redeem CUSD back for USD

Cryptocurrency Support

Name
Symbol
Chain

CUSD on Ethereum

cusdeth

eth

CUSD on EOS

cusdeos

eos

TRXD (Carbon dollar on Tron)

trxd

tron

CUSD on Binance

cusdbinance

binance

CUSD on Telos

tlosd

telos

Fiat Currency Support 💵

Name
Symbol

🇺🇸US Dollar

usd

Payment Methods & Compliance

Separate Stablecoin Compliance Stack Note

Our stablecoin stack enabling minting of CUSD via USD deposits and burning of CUSD for USD withdrawals has a separate KYC/AML process from our other services. Our trust bank, Primetrust, has the burden of compliance as they custody the fiat backing our stablecoin. Therefore, they must run their own bank-level compliance. For this reason, KYC/AML is required for all contacts transacting via the stablecoin stack.

For more information on Primetrust's compliance process, check out https://primetrust.com/compliance

Payment Method
KYC/AML Required?
KYC/AML Provider
Payment Provider

ACH

Yes

Primetrust

Primetrust

Wire

Yes

Primetrust

Primetrust

Transaction Limits

Payment Method
Minimum Single Deposit Amount
Maximum Single Deposit Amount
Maximum Weekly Deposit Amount
Minimum Single Withdrawal Amount
Maximum Single Withdrawal Amount

ACH

25 USD

250 USD

250 USD

25 USD

None

Wire

100 USD

None

None

100 USD

None

If you would like to negotiate transaction limits, please contact daniel at carbon.money and gavin at carbon.money. To clarify, the maximum weekly deposit amount is the maximum amount of money a contact can deposit via the payment method in a week (roughly starting Monday 12:00 PM ET).

Fees

Currently ACH/wire have no fees for deposits and a .1% fee for withdrawals.

JWT Required (Super)

CUSD KYC/AML Overview

Contacts must pass Primetrust's KYC/AML process before purchasing/redeeming CUSD via wire orACH or adding ACH/wire payment methods. This process involves submitting an identity form and uploading identity photos/documentation.
With respect to identity docs, contacts must always upload a government ID. This can be a passport, driver's license, national ID card, or any valid & official form of identity documentation. If the government ID is two-sided, then there must be two uploads: one for the front and for the back. For example passports are one-sided and so will only require one upload while driver's licenses are two-sided and so will require two.
Contacts may optionally upload a proof of address from the past 90 days if their KYC country is 'US' and must upload a proof of address if they are not from the US. A proof of address may include a utility bill, a banking statement, an online receipt (such as that for an Amazon delivery), or any official item of record that displays the contact's name and address dated in the past 90 days. The displayed address must match the one on the uploaded government ID and must not be a p.o. box. Sometimes contacts have to upload a taxpayer id card (in the US this would be a Social Security card) for verification but this is usually not required.
Be sure to check out our webhook docs here for more details on how to listen to compliance process notifications from our KYC/AML provider (relayed from us to you) and the classes of notifications you should prepare to expect. In summary, you will receive notifications on when contacts pass or do not pass KYC/AML. If contacts do not pass KYC/AML, they will have associated CIP (Customer Information Program) exceptions or AML exceptions. We will relay updates with respect to what those are and how to resolve them to your webhook and to the contact's listed email address. Resolutions usually include patching the contact's identity form because CIP information was missing/not verified or uploading new documents to verify identity information that could not be verified through the form or was not matching b/t the form and the previously uploaded documentation. Since emails will be sent to the contact with this CIP/AML exception information, be sure to provider easy access for them to patch their identity forms and submit new documentation.
Contacts can either submit their KYC information form as an individual or institution (businesses and organizations chiefly). The data required for each request are detailed below. Institutions will also have to upload a company charter document in addition to the typical document requirements for an individual (uploading a document for an individual versus an institution is the same programmatically). Institutions must have one individual from the company submit KYC and they will pass in their information along with the institution's KYC information detailed below.

API

1a. Submit KYC/AML compliance application forms (individual)

POST
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';

let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/submitKYC`;

let data = {
  contactId: "ab5bb41b-5979-4a54-b734-23eb9076188e",
  "firstName": "satoshi",
  "lastName": "nakaomoto",
  "dob": "2009-01-03",
  "phoneNumber": "8001371535",
  "street": "1234 bitcoin bld",
  "city": "blockchain",
  "region": "MN",
  "postalCode": "12345",
  "country": "US",
  "taxCountry": "US",
  "taxId": "100000000",
  "sex": "male"
};

axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ message: 'Successfully updated KYC for authenticated contact',
  contactId: '1bb96858-4910-438a-9b51-cbb705712462',
  data: 
   { _id: '5d06ced0ae5edf94739dfe9c',
     publicKeys: {},
     address: 
      { street: '1234 bitcoin bld',
        city: 'blockchain',
        region: 'MN',
        postalCode: '12345',
        country: 'US' },
     paymentMethods: [],
     withdrawals: [],
     deposits: [],
     fiatHistory: [],
     loginAttempts: [],
     dateCreated: '2019-06-16T23:20:48.681Z',
     dateUpdated: '2019-06-16T23:20:51.410Z',
     superId: 'f4c15498-774f-4d75-9f8c-ef64926cc614',
     emailVerified: false,
     id: '1bb96858-4910-438a-9b51-cbb705712462',
     emailAddress: '[email protected]',
     kycPassOnfido: '0',
     kycSent: true,
     kycUpdate: false,
     kycMessage: '',
     kycPhotoUploaded: false,
     googleAuthBool: false,
     enable2fa: false,
     defaultCurrency: 'USD',
     achDepositMax: '250',
     achDepositMin: '25',
     achWeeklyDepositMax: '250',
     achWeeklyBalance: '0',
     jwtToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJmNGMxNTQ5OC03NzRmLTRkNzUtOWY4Yy1lZjY0OTI2Y2M2MTQiLCJjb250YWN0SWQiOiIxYmI5Njg1OC00OTEwLTQzOGEtOWI1MS1jYmI3MDU3MTI0NjIiLCJlbWFpbCI6InNhdG9zaGlAbmFrYW1vdG8uY29tIiwiaWF0IjoxNTYwNzI3MjQ4fQ.7uoyjohqf6m-8Lyn4z2yc7xDSV7wZbg9VEdTjlW4kgE',
     __v: 0,
     dob: '2009-01-03',
     firstName: 'satoshi',
     kycPass: false,
     kycSentOn: '2019-06-16T23:20:51.410Z',
     lastName: 'nakaomoto',
     pTrustId: 'b4205e86-4635-45f9-a632-875359d455fc',
     phoneNumber: '8001371535',
     sex: 'male',
     taxCountry: 'US' } 
}

Request Parameters

Parameters
Access
Description

contactId

required

firstName

required

lastName

required

dob

required

Must be in YYYY-MM-DD (ISO_8601) format

phoneNumber

required

street

required

city

required

region

required

If country is 'US' must be state from set of two-character abbreviations defined in ISO 3166-2:US https://en.wikipedia.org/wiki/ISO_3166-2:US

postalCode

required

If country is 'US' must be 5-digit postal code

country

required

Must be from set of two-character country abbreviations defined in ISO_3166-1_alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

taxCountry

required

Must be from set of two-character country abbreviations defined in ISO_3166-1_alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

taxId

required

If country is 'US' must be a nine-digit Social Security Number (SSN)

sex

required

Must be 'male', 'female', or 'unspecified'

1b. Submit KYC/AML compliance application forms (institutional)

POST

Note the distinction between KYC information for the individual under the institution versus the institution itself in the request parameters below. If there is not a 'personal' prefix for the request parameter, the parameter refers to the institution. Otherwise it refers to the individual under the institution.

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';

let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/submitKYCInstitution`;

let data = {
  contactId: "ab5bb41b-5979-4a54-b734-23eb9076188e",
  personalFirstName: 'Bit',
  personalLastName: 'Coin',
  corporationName: 'The Corporation',
  phoneNumber: '8001371535',
  street: '1 Bit Coin Road',
  city: 'New York',
  region: 'NY',
  postalCode: '10000',
  country: 'US',
  taxCountry: 'US',
  taxId: '100000000',
  personalDob: '2009-01-03',
  personalTaxId: '100000000',
  personalTaxCountry: 'US',
  personalPhoneNumber: '001371535',
  personalSex: 'male',
  personalAddressStreet: '1 Bit Coin Road',
  personalAddressCity: 'New York',
  personalAddressState: 'NY',
  personalAddressCountry: 'US',
  personalAddressPostalCode: '10000',
  personalAddressCountry: 'US',
  companyTaxId: '100000000'
 };

axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ message: 'Successfully submitted KYC for authenticated institutional contact',
  data: 
   { 
     publicKeys: {},
     address: 
      { street: '1 Bit Coin Road',
        city: 'New York',
        region: 'NY',
        postalCode: '10000',
        country: 'US' },
     paymentMethods: [],
     withdrawals: [],
     deposits: [],
     fiatHistory: [],
     loginAttempts: [],
     id: '66538947-ce2e-4ff4-857f-000a8e605e25',
     dateCreated: '2019-07-13T23:56:41.858Z',
     dateUpdated: '2019-07-13T23:56:42.520Z',
     emailVerified: false,
     institutional: false,
     superId: '7bf95df6-2601-4300-90b3-4a2eeabd19fb',
     kycPass: false,
     kycPassOnfido: '0',
     kycSent: true,
     kycUpdate: false,
     remainingWeeklyLimit: '10000',
     weeklyMax: '10000',
     kycMessage: '',
     kycPhotoUploaded: false,
     googleAuthBool: false,
     enable2fa: false,
     creditDebitFailure: 0,
     creditDebitSuccess: 0,
     flaggedContact: false,
     merchant: false,
     defaultCurrency: 'USD',
     achDepositMax: '250',
     achDepositMin: '25',
     achWeeklyDepositMax: '250',
     achWeeklyBalance: '0',
     authenticateCode: null,
     pTrustId: '1a267713-66b2-4fad-bbe9-a0ebdf3a3ad0',
     kycSentOn: '2019-07-13T23:56:42.520Z',
     dob: '2009-01-03',
     phoneNumber: '8001371535',
     taxCountry: 'US',
     personalFirstName: 'Bit',
     personalLastName: 'Coin',
     personalDob: '2009-01-03',
     personalTaxCountry: 'US',
     personalPhoneNumber: '001371535',
     personalSex: 'male',
     personalAddressStreet: '1 Bit Coin Road',
     personalAddressCity: 'New York',
     personalAddressCountry: 'US',
     personalAddressPostalCode: '10000',
     companyTaxId: '100000000',
     corporationName: 'The Corporation' } 
 }

Request Parameters

Parameters
Access
Description

contactId

required

personalFirstName

required

personalLastName

required

corporationName

required

phoneNumber

required

street

required

city

required

region

required

AKA state, province, county given the country terminology. If country is 'US' must be state from set of two-character abbreviations defined in ISO 3166-2:US https://en.wikipedia.org/wiki/ISO_3166-2:US

postalCode

required

If country is 'US' must be 5-digit postal code

country

required

Must be from set of two-character country abbreviations defined in ISO_3166-1_alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

taxCountry

required

Must be from set of two-character country abbreviations defined in ISO_3166-1_alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

taxId

required

If 'taxCountry' is 'US' must be a nine-digit Social Security Number (SSN)

personalDob

required

Must be in YYYY-MM-DD (ISO_8601) format

personalTaxId

required

If 'personalTaxCountry' is 'US' must be a nine-digit Social Security Number (SSN)

personalTaxCountry

required

Must be from set of two-character country abbreviations defined in ISO_3166-1_alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

personalPhoneNumber

required

personalSex

required

'male', 'female', or 'unspecified'

personalAddressStreet

required

personalAddressCity

required

personalAddressState

required

AKA region, province, county given the country terminology.
If 'personalAddressCountry' is 'US' must be state from set of two-character abbreviations defined in ISO 3166-2:US https://en.wikipedia.org/wiki/ISO_3166-2:US

personalAddressPostalCode

required

If 'personalAddressCountry' is 'US' must be 5-digit postal code

personalAddressCountry

required

Must be from set of two-character country abbreviations defined in ISO_3166-1_alpha-2 https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

companyTaxId

required

If 'taxCountry' is 'US' must be a nine-digit Social Security Number (SSN)

2. Upload identity documentation

POST

Make sure that you specify the 'Content-Type' request header as 'multipart/form-data' and include the boundary specification if necessary.

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';

const FormData = require('form-data');

let formData = new FormData();
let file = fs.readFileSync("test_pic.jpg");
formData.append("file", file, {
  filename:    'test_pic.jpg',
  contentType: "image/jpeg"
} );
formData.append("contactId", testContactUuid);

let formDataToBufferObject = formDataToBuffer( formData );
let contentType = formData.getHeaders()['content-type'];

let headers = {
  headers: {
    Authoriziation: `Bearer ${jwtToken}`,
    'Content-Type': contentType
  }
}


let url = `${ROOT}/v1/contacts/uploadDocument`;



axios.post(url, formDataToBufferObject, headers).then(result => console.log).catch(err => console.log);
{ message: 'Successfully uploaded document.' }

Request Parameters

Parameters
Access
Description

file

required

contactId

required

Approve KYC (sandbox)

POST

In production Primetrust will of course clear KYC. In sandbox a successful response will enable a cleared contact to transact via ACH/wire

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';

let headers = {
  headers: {
    Authoriziation: `Bearer ${jwtToken}`,
  }
}

let data = {
  contactId: testContactUuid
  
};

let url = `${ROOT}/v1/contacts/approveKYC`;



axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ message:  'Successfully approved KYC for contact'}

2. Add an ACH payment method

POST

ACH payment methods are needed when initiating ACH withdrawals to a contact's bank account. For ACH deposits, the bank account number and routing numbers are used to initiate ACH pulls from a contact's bank account.

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';

let headers = {
  headers: {
    Authoriziation: `Bearer ${jwtToken}`
  }
}

let data = {  
  "bankAccountNumber": "123123123",
  "routingNumber": "021000021",
  "bankName": "The Bank",
  "bankAccountType": "checking",
  "contactId": "24162d19-b3c3-43bd-bbca-8a5ae8e55963"
};

let url = `${ROOT}/v1/contacts/paymentMethods/ach`;



axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ 
   message: 'Created an ACH payment method.',
   paymentMethodId: '6a25bdc2-c4ab-435e-8537-f166b014aa55' 
}

Request Parameters

Parameters
Access
Description

bankAccountNumber

required

routingNumber

required

Must conform to ABA standards: https://en.wikipedia.org/wiki/ABA_routing_transit_number#Formats. Feel free to use the test routing number in the code sample above for sandbox testing

bankName

required

bankAccountType

required

Must be either 'checking' or 'savings'

contactId

required

3. Initiate an ACH deposit

POST
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';

let headers = {
  headers: {
    Authoriziation: `Bearer ${jwtToken}`
  }
}

let url = `${ROOT}/v1/contacts/deposits/ach`;

let data = {
  "chain": "eos",
  "address": "testdaniel13",
  "amount": "25",
  "routingNumber": "021000021",
  "bankAccountNumber": "123123123",
  "bankName": "The Bank",
  "bankAccountType": "checking",
  "contactId": "24162d19-b3c3-43bd-bbca-8a5ae8e55963"
};



axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{
 message: 'Created an ach deposit.',
 depositId: '',
 pTrustFundsTransferId: '',
 amount: '25',
 chain: 'eos',
 address: 'testdaniel13'
};
Parameters
Access
Description

chain

required

Must be either 'eth', 'eos', 'tron', ‘binance’, or ‘telos’.

address

required

Must be a blockchain address associated with the designated 'chain'

amount

required

Must be a string conforming to the ACH transaction limits specified in the table above.

routingNumber

required

Must conform to ABA standards: https://en.wikipedia.org/wiki/ABA_routing_transit_number#Formats. Feel free to use the test routing number in the code sample above for sandbox testing

bankAccountNumber

required

bankName

required

bankAccountType

required

contactId

required

4. Initiate an ACH withdrawal

POST
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authoriziation: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/withdrawals/ach`;

let data = {
   "chain": "eos",
    "address": "testdaniel3",
   "amount": "1000",
   "paymentMethodId": testContactAchPmId,
   "txHash": "a",
   "contactId": testContactUuid
};


axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
 {
   message: 'Created a wire payment method.',
   paymentMethodId: ''
 };
Parameters
Access
Description

chain

required

Must be either 'eth', 'eos', 'tron', ‘binance’, or ‘telos’.

address

required

Must be a blockchain address associated with the designated 'chain'

amount

required

Must be a string conforming to the ACH transaction limits specified in the table above

paymentMethodId

required

txHash

required

Burn transaction id

contactId

required

5. Add a wire payment method (domestic)

POST
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/paymentMethods/wire`;

let data = {
  contactId: testContactUuid,
  isBankInternational: false,
  bankName: 'Chase for Bitcoin',
  bankAccountNumber: '123123123',
  routingNumber: '021000021',
  beneficiaryAddress: {
    'street-1': '123 MLK Drive',
    city: 'Las Vegas',
    country: 'US',
    region: 'NV',
    'postal-code': '89145'
}


axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ message: 'Created an ach withdrawal.',
  withdrawalId: 'd24a6b4c-6bc3-43aa-a867-a2a310bb23be',
  pTrustFundsTransferId: '486117d8-7230-49d7-8bd5-c21fa5a3aaf9',
  amount: '100' 
 }
Parameters
Access
Description

contactId

required

isBankInternational

required

Boolean (true, false). Whether wire payment method is for a United States bank or an international bank. For domestic this will be false.

bankName

required

Example 'Chase Bank'

bankAccountNumber

required

routingNumber

required (domestic)

Required if isBankInternational is false. Must conform to ABA standards: https://en.wikipedia.org/wiki/ABA_routing_transit_number#Formats. Feel free to use the test routing number in the code sample above for sandbox testing

beneficiaryAddress

required (as higher-level object. required keys are highlighted in the rows below).

the address of the person under the bank account initiating the wire.

beneficiaryAddress['street-1']

required

beneficiaryAddress['city']

required

beneficiaryAddress['country']

required

Must be 'US' for domestic

beneficiaryAddress['region']

required

if domestic must be 'US' state from set of two-character abbreviations defined in ISO 3166-2:US https://en.wikipedia.org/wiki/ISO_3166-2:US

beneficiaryAddress['postal-code']

required

If domestic must be 5-digit 'US' postal code

beneficiaryAddress['street-2']

optional

Extra information to specify for street for a contact, such as an apartment number.

6.Initiaite wire deposit

POST

Note that a contact must initiate a wire deposit themselves of the specified amount through their bank. The information needed for the wire recipient (our trust bank) will be included in the response body. For convenience it is listed in the sample response body below and also here:
beneficiaryName: 'Prime Trust, LLC'
bankAddress: '949 South Coast Drive, Third Floor Costa Mesa, CA 92626'
bankName: 'Pacific Mercantile Bank'
bankPhone: '+1-714-438-2500'
beneficiaryAddress: '330 S Rampart Ave, Suite 260 Las Vegas, NV, 89145'
routingNumber: '122242869'
accountNumber: '45585603'
swiftCode: 'PMERUS66'
}

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/deposits/wire`;

let data = {
   contactId: '',
   amount: '1000000',
   chain: 'tron',
   address: 'TH2kMhFF4hk6xYZMeyz6zEFBA8tg8cTXge'
};

axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ message: 'Created a wire deposit.',
  depositId: '7e4f2f8d-2535-4c13-94a7-d199774ccea2',
  pTrustFundsTransferId: '55c0f7e7-fb4e-41d6-9d88-348d2413464f',
  wiringAddress: 
   { beneficiaryName: 'Prime Trust, LLC',
     bankAddress: '949 South Coast Drive, Third Floor Costa Mesa, CA 92626',
     bankName: 'Pacific Mercantile Bank',
     bankPhone: '+1-714-438-2500',
     beneficiaryAddress: '330 S Rampart Ave, Suite 260 Las Vegas, NV, 89145',
     routingNumber: '122242869',
     accountNumber: '45585603',
     swiftCode: 'PMERUS66' },
  amount: '1000000',
  chain: 'tron' }
Parameters
Access
Description

contactId

required

amount

required

Must be a string conforming to the wire transaction limits specified in the table above.

chain

required

Must be either 'eth', 'eos', 'tron', ‘binance’, or ‘telos’.

address

required

Must be a blockchain address associated with the designated 'chain'

6. Initiate a wire withdrawal

POST
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/withdrawals/wire`;

let data = {
   contactId: '',
  chain: 'tron',
  amount: '100',
  paymentMethodId: '',
  address: 'TH2kMhFF4hk6xYZMeyz6zEFBA8tg8cTXge',
  txHash: ''
};

axios.post(url, data, headers).then(result => console.log).catch(err => console.log);
{ message: 'Created a wire withdrawal.',
  withdrawalId: 'd24a6b4c-6bc3-43aa-a867-a2a310bb23be',
  pTrustFundsTransferId: '486117d8-7230-49d7-8bd5-c21fa5a3aaf9',
  amount: '100' 
 }

7. Get All Stablecoin Payment Methods

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let url = `${ROOT}/v1/contacts/stablecoinPaymentMethods/all?contactId=${contactId}`;


axios.get(url, headers).then(result => console.log(result)).catch(err => console.log(err));
{ details: 
   [ { id: '',
       type: 'ach',
       datetimeCreated: '2019-10-31T01:46:52.755Z',
       bankName: 'The Bank',
       routingNumber: '021000021',
       accountNumber: '123123123',
       contactId: '',
       pTrustPaymentId: '',
       swiftCode: null 
     },
   ],
  message: 'Obtained stablecoin payment methods under contact.',
  code: 200 
}

8. Get Deposit By Id

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let contactId = '';
let depositId = '';

let url = `${ROOT}/v1/contacts/deposits/${depositId}?contactId=${contactId}`;


axios.get(url, headers).then(result => console.log(result)).catch(err => console.log(err));
 { message: 'Found stablecoin deposit.',
     data: 
      { id: '',
        datetimeInitiated: '2019-11-07T00:26:48.505Z',
        complete: true,
        chain: 'telos',
        address: 'stablecarbon',
        pTrustDepositId: '388dc4d3-e53d-4037-886a-267b1eb1c46a',
        pTrustFundsTransferId: 'c1cfc8c2-fc6a-4424-9cf1-c72517277b87',
        amount: '1000000',
        status: 'settled',
        contactId: '',
        paymentType: 'wire',
        dateCompleted: '2019-11-07T00:27:26.687Z',
        mintTxId: 'ee91c151d1c1d3a8c89d5934d115ec3759b55478c0d099c2882d19b5b0eb9e16' 
      } 
 } 
}

9. Get All Deposits (under contact)

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let contactId = '';

let url = `${ROOT}/v1/contacts/deposits/all?contactId=${contactId}`;


axios.get(url, headers).then(result => console.log(result)).catch(err => console.log(err));
 
{ 
  message: 'Retrieved deposits under contact',
  code: 200,
  data:  
  [ 
    { wiringAddress: 
     { 
       beneficiaryName: 'Prime Trust, LLC',
       bankAddress: '949 South Coast Drive, Third Floor Costa Mesa, CA 92626',
       bankName: 'Pacific Mercantile Bank',
       bankPhone: '+1-714-438-2500',
       beneficiaryAddress: '330 S Rampart Ave, Suite 260 Las Vegas, NV, 89145',
       routingNumber: '122242869',
       accountNumber: '45585603',
       swiftCode: 'PMERUS66' 
     },
    id: '',
    datetimeInitiated: '2019-11-07T00:26:48.505Z',
    complete: true,
    chain: 'telos',
    address: 'stablecarbon',
    pTrustDepositId: '388dc4d3-e53d-4037-886a-267b1eb1c46a',
    pTrustFundsTransferId: 'c1cfc8c2-fc6a-4424-9cf1-c72517277b87',
    amount: '1000000',
    status: 'settled',
    contactId: 'a6288522-e61d-4115-87a5-db17837db83b',
    paymentType: 'wire',
    dateCompleted: '2019-11-07T00:27:26.687Z',
    mintTxId: 'ee91c151d1c1d3a8c89d5934d115ec3759b55478c0d099c2882d19b5b0eb9e16'
    }
  ]
}

10. Settle Deposit (testnet)

Initiate settlement of a deposit in testnet to trigger minting. In production, you will have to wait for a deposit to settle into our trust bank's escrow account from a user's bank account before we mint. Confirmation emails for contacts registered with email addresses will be sent in sandbox and production for mints.

let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';


let headers = {
  headers: {
    Authorization: `Bearer ${jwtToken}`
  }
};

let data = {
  contactId: '',
  depositId: ''
}

let url = `${ROOT}/v1/contacts/settleDeposit`;


axios.post(url, data, headers).then(result => console.log(result)).catch(err => console.log(err));
{ 
  message: 'Deposit settled!',
  code: 200
}

File Upload Helper Functions

Code for formDataToBuffer helper function for serializing formData into a buffer request body & extracting the Content-Type request header. This helper function in our experience is the most consistent and reliable way to send form data involving files of different content types interacting with different servers handling uploaded files in various ways. Feel free to upload files in whatever way works for you with our API.

const FormData = require('form-data');


function formDataToBuffer( formData ) {
  let dataBuffer = new Buffer( 0 );
  let boundary   = formData.getBoundary();
  for( let i = 0, len = formData._streams.length; i < len; i++ ) {

      if( typeof formData._streams[i] !== 'function' ) {

          dataBuffer = bufferWrite( dataBuffer, formData._streams[i] );


          if( typeof formData._streams[i] !== 'string' || formData._streams[i].substring( 2, boundary.length + 2 ) !== boundary ) {
              dataBuffer = bufferWrite( dataBuffer, "\r\n" );
          }
      }
  }

  dataBuffer = bufferWrite( dataBuffer, '--' + boundary + '--' );

  return dataBuffer;
}

function bufferWrite( buffer, data ) {

  let addBuffer;
  if( typeof data === 'string' ) {
      addBuffer = Buffer.from( data );
  }
  else if( typeof data === 'object' && Buffer.isBuffer( data ) ) {
      addBuffer = data;
  }

  return Buffer.concat( [buffer, addBuffer] );
}


Thank you for your feedback

CarbonUSD


Purchase CUSD with USD and redeem CUSD back for USD

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.