Carbon

Documentation

Welcome to Carbon's docs!

Get Started    

Complete Payment; Custom Term URL

As you may recall from the Credit/Debit Purchases API page, the response to your /v1/card/charge3d POST request includes a termurl for 3D Secure enrolled cards.

This URL is used as part of the form submission to the card issuer Access Control Server (ACS) where the cardholder's identity is verified, as we covered in our 3D Secure Card Payments Overview.

Following verification, the ACS sends a POST request to the Term URL with the necessary information for the card to be charged and for the transaction to be processed.

Carbon provides the Term URL in most cases

This way, less development is required by you, the integrator.

We now provide the option of providing your own Term URL (required for payment gateway)

Providing your own Term URL gives you more freedom to control the end user purchase flow

Please contact [email protected] for more information.

Setting Superuser Term URL

Example request/response

// legacy auth that will be deprecated in our v2 api
/*
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';
*/
// we strongly recommend using your secret key to more securely authenticate your superuser instead
let secretKey = 'sk_test_A41Hm6IY3Q5LJ7ham34Zpkcj';

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


let url = `${ROOT}/v1/admin`;

let data = {
  termUrl: 'https://sandbox.carbon.money/termUrl',
}

axios.put(url, data, headers).then(result => console.log(result)).catch(err => console.log(err));
{ 
  message: 'Successfully updated superuser config.',
  details: { 
    termUrl: 'https://sandbox.carbon.money/termUrl' 
  },
  code: 200 
}
// 500
{
  message: 'Error setting superuser config.',
  code: 500
}

Getting Superuser Term URL

// legacy auth that will be deprecated in our v2 api
/*
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';
*/
// we strongly recommend using your secret key to more securely authenticate your superuser instead
let secretKey = 'sk_test_A41Hm6IY3Q5LJ7ham34Zpkcj';

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

let url = `${ROOT}/v1/admin`;


axios.get(url, headers).then(result => console.log(result)).catch(err => console.log(err));
{ 
  message: 'Successfully retrieved superuser config.',
  details: { 
    termUrl: 'https://sandbox.carbon.money/termUrl'
  },
  code: 200 
}
// 500
{
  message: 'Error getting superuser config.',
  code: 500
}

Requirements for Term URL

  • MUST check for PaRes and MD in the request body (case-sensitive)
  • MUST call either /v1/card/charge3d/auth or /v1/card/charge3d/auth/cancel before sending a response
  • MUST handle errors from /v1/card/charge3d/auth as detailed in the section below
  • MUST complete the delivery of the asset following a successful charge
  • MUST notify Carbon of the completion of the purchase using /v1/card/charge3d/auth/complete
  • SHOULD notify the user of the completion of the purchase

When the purchase is completed, the response that your Term URL sends will be rendered in your front end, or you can redirect to a different route.

Authorization (charging the user's card)

Example request/response

// legacy auth that will be deprecated in our v2 api
/*
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';
*/
// we strongly recommend using your secret key to more securely authenticate your superuser instead
let secretKey = 'sk_test_A41Hm6IY3Q5LJ7ham34Zpkcj';

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

let url = `${ROOT}/v1/card/charge3d/auth`;

let data = {
  MD: "UEZOVVBqeE5SRDQ4VFVSSVBrbFhaRTQyZGtOblUwSllSV3B5YlRZeGJ6bHdlbWM5UFR3dlRVUklQanhoWTNOVmNtdythSFIwY0hNNkx5OTNaV0poY0hBdWMyVmpkWEpsZEhKaFpHbHVaeTV1WlhRdllXTnpMMjFoYzNSbGNtTmhjbVF1WTJkcFBDOWhZM05WY213K1BIQmhia3hsYm1kMGFENHhOand2Y0dGdVRHVnVaM1JvUGp4dFpYTnpZV2RsU1dRK1VFRlNaWEV0TVRVMk9UazNNemMxT0RVeU1pMHRNekF4TnpjeU1ETTVQQzl0WlhOellXZGxTV1ErUEM5TlJENDhMMU5VUGc9PTptZGZGaXRCR0pBdDlQWkZqMmJsRFAySE5kcncyYjN2MjJnTUZVTEVtcHhiYUgzQU4veERVNE9MMVZ3VmZFTlFMUDE",
  PaReS: "eJxVUl1PwjAU/SvEd3bXjrGNXJr4GU2EGJQYfCvtjSy6bnadGf562wmKfbrn3O97ik87S3T1SKqzJHBBbStfaVTq+dnD+Yo+xiydFkWWZGmecj4eJzHLMh4nxZnAIUDgJ9m2rI1gURxxhCP0tazaSeMESvVxcbcU03SScIZwgFiRvbsS8f+H8EOjkRWJS2m3tRktakP7EcLAoao74+xe5HyKcATY2Xexc65pZwCtNHpb95Ea0qMqpMMnA2VJl86zGvxo9pUSDbIpVV017+QIIRRB+Jv8oQtW65v2pRbb61W/edPxYp/3z2WxXt8sly+mebz/2swRQgRq6UjwmBUsjtmIJ7NJMWM5wsCjrMK0gvGw5wFgE3qcn3pOGfTCWDLKrzvxrl+E1Dd+LR/hb/5ro6ZWidpqsr5nsBH+dri8DVoo58+bspObp2xQZXCEuqW/pxf6p3AACCEVDoLD4Zd469/v+QY8W7/8"
}

axios.post(url, data, headers).then(result => console.log(result)).catch(err => console.log(err));
// 403
// example w/ limit: $250, charge: $250.01 
{
  message: 'Your daily limit is exceeded with remaining $250.00 with a charge of $250.01. Please try transacting with a smaller amount. Also you can go through KYC to increase your daily limits to $2500'
  code: 403
}
Params
Access
Description

MD

Required

Exact same as the property sent from the ACS

PaRes

Required

Exact same as the property sent from the ACS

Error Handling

In the case that you receive a 200 response with success:false in the body, you can display the error log (or your own message) to the user for them to resolve the issue. This is most likely fixed by the user double checking their card information, or contacting their bank, which may have blocked the charge.

Next steps...

Once you have received confirmation the user's card has been charged, it is your responsibility to deliver their assets and then confirm with Carbon that the purchase is completed using the /v1/card/charge3d/auth/complete route.

You must confirm the completion of every purchase

If we do not receive a confirmation that the purchase has been filled, we will cancel the charge on the card without warning. You will have up to 6 hours to send the confirmation.

We understand that errors happen, but if an error occurs in the delivery of the goods to the user we need to cancel the charge on the user's card as soon as possible. You can cancel the charge with the /v1/card/charge3d/auth/cancel route.

After a charge has settled (~24 hours after the initial authorization), a cancellation cannot be processed. If a user contests a charge or needs to be refunded for some reason after this window, you can use /v1/card/charge3d/auth/refund to process a refund.

Completing the purchase (example)

// legacy auth that will be deprecated in our v2 api
/*
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';
*/
// we strongly recommend using your secret key to more securely authenticate your superuser instead
let secretKey = 'sk_test_A41Hm6IY3Q5LJ7ham34Zpkcj';

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

let url = `${ROOT}/v1/card/charge3d/auth/complete`;

let data = {
  MD: "UEZOVVBqeE5SRDQ4VFVSSVBrbFhaRTQyZGtOblUwSllSV3B5YlRZeGJ6bHdlbWM5UFR3dlRVUklQanhoWTNOVmNtdythSFIwY0hNNkx5OTNaV0poY0hBdWMyVmpkWEpsZEhKaFpHbHVaeTV1WlhRdllXTnpMMjFoYzNSbGNtTmhjbVF1WTJkcFBDOWhZM05WY213K1BIQmhia3hsYm1kMGFENHhOand2Y0dGdVRHVnVaM1JvUGp4dFpYTnpZV2RsU1dRK1VFRlNaWEV0TVRVMk9UazNNemMxT0RVeU1pMHRNekF4TnpjeU1ETTVQQzl0WlhOellXZGxTV1ErUEM5TlJENDhMMU5VUGc9PTptZGZGaXRCR0pBdDlQWkZqMmJsRFAySE5kcncyYjN2MjJnTUZVTEVtcHhiYUgzQU4veERVNE9MMVZ3VmZFTlFMUDE",
  transactionHash: "d998f3e24dc53a1dd7b10ea04caf9619357f546b88f342d818ccf42a1f714eef"
}

axios.post(url, data, headers).then(result => console.log(result)).catch(err => console.log(err));
Params
Access
Description

MD

Required

Used as a unique identifier for the order

transactionHash

Required

On chain transaction ID, showing proof of delivery for the associated purchase on the user's card

Cancellations and Refunds

Cancellation example

// legacy auth that will be deprecated in our v2 api
/*
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';
*/
// we strongly recommend using your secret key to more securely authenticate your superuser instead
let secretKey = 'sk_test_A41Hm6IY3Q5LJ7ham34Zpkcj';

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

let url = `${ROOT}/v1/card/charge3d/auth/cancel`;

let data = {
  MD: "UEZOVVBqeE5SRDQ4VFVSSVBrbFhaRTQyZGtOblUwSllSV3B5YlRZeGJ6bHdlbWM5UFR3dlRVUklQanhoWTNOVmNtdythSFIwY0hNNkx5OTNaV0poY0hBdWMyVmpkWEpsZEhKaFpHbHVaeTV1WlhRdllXTnpMMjFoYzNSbGNtTmhjbVF1WTJkcFBDOWhZM05WY213K1BIQmhia3hsYm1kMGFENHhOand2Y0dGdVRHVnVaM1JvUGp4dFpYTnpZV2RsU1dRK1VFRlNaWEV0TVRVMk9UazNNemMxT0RVeU1pMHRNekF4TnpjeU1ETTVQQzl0WlhOellXZGxTV1ErUEM5TlJENDhMMU5VUGc9PTptZGZGaXRCR0pBdDlQWkZqMmJsRFAySE5kcncyYjN2MjJnTUZVTEVtcHhiYUgzQU4veERVNE9MMVZ3VmZFTlFMUDE"
}

axios.post(url, data, headers).then(result => console.log(result)).catch(err => console.log(err));
Params
Access
Description

MD

Required

Used as a unique identifier for the order

Charges that have already settled cannot be cancelled

If the charge has a status of 100, the charge has settled and must be refunded, not cancelled.

Refund example

Refunds incur a small fee

Your first 10 refunds each month are free, each additional refund will incur a fee of $1.25 subtracted from your settled volume. We do not make a profit on refunds.

// legacy auth that will be deprecated in our v2 api
/*
let jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJlMzE3YjdlNy0yMzQ1LTQ0MWMtODA0Ni1kYjgxNTkyYmEyN2YiLCJzdXBlclVzZXIiOnRydWUsImNvbnRhY3QiOmZhbHNlLCJlbWFpbCI6ImRhbmllbEBjYXJib24ubW9uZXkiLCJpYXQiOjE1NTczMjc5MTR9.WZnSR5N1FebmT9nMu97PJvku49NY0jk4aKVPKm_1MlM';
*/
// we strongly recommend using your secret key to more securely authenticate your superuser instead
let secretKey = 'sk_test_A41Hm6IY3Q5LJ7ham34Zpkcj';

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

let url = `${ROOT}/v1/card/charge3d/auth/refund`;

let data = {
  MD: "UEZOVVBqeE5SRDQ4VFVSSVBrbFhaRTQyZGtOblUwSllSV3B5YlRZeGJ6bHdlbWM5UFR3dlRVUklQanhoWTNOVmNtdythSFIwY0hNNkx5OTNaV0poY0hBdWMyVmpkWEpsZEhKaFpHbHVaeTV1WlhRdllXTnpMMjFoYzNSbGNtTmhjbVF1WTJkcFBDOWhZM05WY213K1BIQmhia3hsYm1kMGFENHhOand2Y0dGdVRHVnVaM1JvUGp4dFpYTnpZV2RsU1dRK1VFRlNaWEV0TVRVMk9UazNNemMxT0RVeU1pMHRNekF4TnpjeU1ETTVQQzl0WlhOellXZGxTV1ErUEM5TlJENDhMMU5VUGc9PTptZGZGaXRCR0pBdDlQWkZqMmJsRFAySE5kcncyYjN2MjJnTUZVTEVtcHhiYUgzQU4veERVNE9MMVZ3VmZFTlFMUDE"
}

axios.post(url, data, headers).then(result => console.log(result)).catch(err => console.log(err));
Params
Access
Description

MD

Required

Used as a unique identifier for the order

Complete Payment; Custom Term URL


Suggested Edits are limited on API Reference Pages

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