Skip to main content

Merchant Help Center

 

Affirm Merchant Help Center

Direct API

This guide will walk you through a direct API integration with Affirm.

 

Overview

Integration Points
  • Checkout flow
    • Add new Affirm payment method.
    • Write code to populate checkout object and initiate checkout.
  • Authorization page
    • Receive the checkout_token.
    • Write code to authorize charge, store charge ID, and redirect to order confirmation.
       
  • Order management system
    • Initiate charge actions.
    • Associate Affirm charge ID with orders, mark orders as paid with Affirm. 
       
  • Error handling
    • Educate or reach out to users with an unsuccessful Affirm checkout.
    • Block order fulfillment if authorization or capture is unsuccessful.
    • Log errors for admins.
User Flow

  1. User selects Affirm payment method during checkout
  2. User submits checkout
  3. Merchant populates 'affirm.checkout({ })' object
  4. Merchant calls 'affirm.checkout.post()' function
  5. User is redirected to Affirm
  6. User logs in or creates an account with Affirm
  7. User selects loan terms
  8. User confirms loan terms
  9. Affirm sends checkout_token to user_confirmation_url
  10. User is redirected to user_confirmation_url
  11. Merchant parses checkout_token
  12. Merchant sends authorization request using checkout_token to Affirm
  13. Affirm sends authorization success response
  14. Merchant parses authorization response and stores charge_id
  15. Merchant redirects user to order confirmation page
  16. Order is complete


Merchant account setup

How to access your Affirm merchant account credentials.
Google Account

You will need a Google account to login to the dashboard.

  • If your current email address isn't associated with a Google account, you can do so here: 
    Sign up without Gmail
     
  • If your company uses Gmail, or if you already have a Google account, you can login with those credentials.

Go to the Merchant Dashboard

You can access the sandbox environment Merchant Dashboard here:

https://sandbox.affirm.com/dashboard

Sign in with your Google account. If you aren't able to login, or receive a Internal Server Error, you may not have access to this dashboard or the dashboard may not be enabled. Please contact merchanthelp@affirm.com to restore your access.

Affirm Merchant Sandbox Dashboard

  1. Go to: https://sandbox.affirm.com/dashboard.
  2. Use your Google account credentials to login.

Retrieve Sandbox Keys

Once you are in the Merchant Dashboard, use the navigation bar on the left to access your API Keys. You will need the public key, private key, and financial product key that is displayed here.

  1. Hover over the profile icon area at the lower-left of the page.
    Screen Shot 2016-03-22 at 7.56.58 AM-2.png
  2. Click the API Keys link that appears.
    Screen Shot 2016-03-22 at 7.56.20 AM.png
  3. Copy the public, private, and financial product keys.


Sandbox environment setup


Initiate checkout

[Affirm.js] affirm.checkout().post
Embed Affirm's JS runtime code

<script>
  var _affirm_config = {
    public_api_key:  "XXXXXXXXXXXXXXX",
    script:          "https://cdn1-sandbox.affirm.com/js/v2/affirm.js"
  };
  (function(l,g,m,e,a,f,b){var d,c=l[m]||{},h=document.createElement(f),n=document.getElementsByTagName(f)[0],k=function(a,b,c){return function(){a[b]._.push([c,arguments])}};c[e]=k(c,e,"set");d=c[e];c[a]={};c[a]._=[];d._=[];c[a][b]=k(c,a,b);a=0;for(b="set add save post open empty reset on off trigger ready setProduct".split(" ");a<b.length;a++)d[b[a]]=k(c,e,b[a]);a=0;for(b=["get","token","url","items"];a<b.length;a++)d[b[a]]=function(){};h.async=!0;h.src=g[f];n.parentNode.insertBefore(h,n);delete g[f];d(g);l[m]=c})(window,_affirm_config,"affirm","checkout","ui","script","ready");
 // Use your live public API Key and https://cdn1.affirm.com/js/v2/affirm.js script to point to Affirm production environment.
</script>

Once the Affirm JS is initialized, the affirm.checkout methods are made available:

  • affirm.checkout({ }) - Stores the checkout object and is used for the checkout request payload.
  • affirm.checkout.post() - Sends the checkout object via POST request.
Define runtime parameters

The Affirm environment that's used is determined by the Affirm script URL that's defined in the _affirm_config.script:

var _affirm_config = {
    public_api_key:  "XXXXXXXXXXXXXXX",
    script:          "https://cdn1-sandbox.affirm.com/js/v2/affirm.js"
  };
Checkout object

This is the data payload that gets POSTed to the Affirm API to initialize checkout.

affirm.checkout({

      "merchant": {
        "user_confirmation_url":    "https://merchantsite.com/confirm",
        "user_cancel_url":          "https://merchantsite.com/cancel"
        "user_confirmation_url_action": "POST",
        "name": "Your Customer-Facing Merchant Name"
      },
      "shipping":{
        "name":{
          "first":"John",
          "last":"Doe"
          // You can include the full name instead
          // "full" : "John Doe"
        },
        "address":{
          "line1":"325 Pacific Ave",
          "city":"San Francisco",
          "state":"CA",
          "zipcode":"94112",
          "country":"USA"
        }
        "phone_number": "4151234567",
        "email": "johndoe@gmail.com"
      },
      "billing":{
        "name":{
          "full":"John Doe"
        },
        "address":{
          "line1":"325 Pacific Ave",
          "city":"San Francisco",
          "state":"CA",
          "zipcode":"94112",
          "country":"USA"
        }
        "phone_number": "4151234567",
        "email": "johndoe@gmail.com"
      },
      "items": [{
        "display_name":         "Awesome Pants",
        "sku":                  "ABC-123",
        "unit_price":           1999,
        "qty":                  3,
        "item_image_url":       "http://merchantsite.com/images/awesome-pants.jpg",
        "item_url":             "http://merchantsite.com/products/awesome-pants.html"
      }],

      "discounts": {
        "RETURN5": {
          "discount_amount":    500,
          "discount_display_name": "Returning customer 5% discount"
        },
        "PRESDAY10": {
          "discount_amount":    1000,
          "discount_display_name": "President's Day 10% off"
        }
      },

      "metadata": {
        "shipping_type":        "UPS Ground",
        "entity_name":          "internal-sub_brand-name"
      },

      "order_id":               "JKLMO4321",

      "shipping_amount":        1000,
      "tax_amount":             500,
      "total":                  6997

  });
 
merchant
required object. Define the URLs for the two results of a checkout attempt and an optional external name.
shipping
required object. Customer contact information.
billing
optional object. Customer contact information.
items
required list. A list of item objects.
discounts
optional hash. A hash of coupon codes to discount objects. If discounts are passed, they must have a name and positive integer dollar amount.
metadata
optional object. A hash of keys to values for any metadata to be passed into checkout and stored. 'entity_name' is a protected key, and will show up in your settlement reporting.
order_id
optional string. Your internal order id. This is stored for your own future reference.
shipping_amount
required integer. The total shipping amount; Defaults to 0.
tax_amount
required integer. The total tax amount computed after all discounts have been applied; Defaults to 0.
total
required integer. The total amount of the checkout. This determines the total amount charged to the user.

 

Merchant object

The merchant object contains the user_confirmation_url and user_cancel_url, which represent the two possible outcomes of the checkout attempt. The user goes to the confirmation_url if the user is approved and confirms their loan. The user goes to the cancel_url in all other cases (voluntary cancel, credit decline, identity verification issue, etc.). 

"merchant": {
    "user_confirmation_url":    "https://merchantsite.com/confirm",
    "user_cancel_url":          "https://merchantsite.com/cancel",
    "user_confirmation_url_action": "POST", // or "GET"
    "name":          "External Company Name"
     },
user_confirmation_url
required url. URL that the customer is sent to if they successfully complete the Affirm checkout flow. 
A checkout_token will be sent to this URL in the POST request, and that checkout_token should be used to authorize the charge before the user is redirected to the order confirmation page.
Analytics tags are other query string parameters can be persisted here as well. Read more here.
user_cancel_url
required url. URL that the customer is sent to if the customer exits the Affirm checkout flow.
This is the same if the user voluntarily cancels or closes the window before completion, or if the user is denied. You should setup the cancel_url to be the checkout payment page, and you can also append analytics tags to the URL to help you identify who you may want to reach out to about alternative payment methods or reapplying. 
Analytics tags are other query string parameters can be persisted here as well. Read more here.
user_confirmation_url_action
optional string. Accepted values are: 'GET', 'POST'. Defaults to 'POST'. Read more here.
name
optional string. If you have multiple sites operating under a single Affirm account, you can override the external company/brand name that the customer sees. This affects all references to your company name in the Affirm UI.

Contact object
  • 'shipping' object is required. 'billing' object is optional. Both have the same format as a contact object/

"shipping":{
        "name":{
          "first":"John",
          "last":"Doe"
          // You can include the full name instead
          // "full" : "John Doe"
        },
        "address":{
          "line1":"325 Pacific Ave",
          "city":"San Francisco",
          "state":"CA",
          "zipcode":"94112",
          "country":"USA"
        }
        "phone_number": "4151234567",
        "email": "johndoe@gmail.com"
      }
 "billing":{
        "name":{
          "first":"John",
          "last":"Doe"
          // You can include the full name instead
          // "full" : "John Doe"
        },
        "address":{
          "line1":"325 Pacific Ave",
          "city":"San Francisco",
          "state":"CA",
          "zipcode":"94112",
          "country":"USA"
        }
        "phone_number": "4151234567",
        "email": "johndoe@gmail.com"
      }
(object key name)
required string. Either 'shipping' or 'billing'. Only the 'shipping' object is required, 'billing' object is optional.
name
required object. First and last, or full name. Used to pre-populate the account sign-up form.
address
required object. Address information. Validated against public address service APIs.
phone_number
optional string. The user's phone number. Validated against the Affirm checkout API. Must be a valid, U.S.-based, mobile phone number. Used to pre-populate the account sign-up form.
email
optional string. The user's email address.

 

Address object

"address":{
   "line1":"633 Folsom St",
   "city":"San Francisco",
   "state":"CA",
   "zipcode":"94107",
   "country":"USA"
}
line 1
required string. Valid U.S. street address, verified by public address service APIs.
line 2
optional string. Apartment, suite, floor, etc. 
city
required string. City name, verified by public address service APIs.
state
required string. 2-letter ISO code or full name, verified by public address service APIs.
zipcode
required string. Must match other provided address information, verified by public address service APIs.
country
optional string. If provided, must be 'US' or 'USA' (3-letter ISO code). Affirm is only available to U.S. residents.

Name object 

"name":{
   "first": "Ben",
   "last": "Mo",
   "full": "Ben Mo"
}
first
required string. Can contain multiple words (for middle names).
last
required string.
full
optional string. Required if 'first' and 'last' keys are missing. String must contain at two words.

Item object

The item object array should be built dynamically, based on the current cart contents.

"items": [{
        "display_name":         "Awesome Pants",
        "sku":                  "ABC-123",
        "unit_price":           1999,
        "qty":                  3,
        "item_image_url":       "http://merchantsite.com/images/awesome-pants.jpg",
        "item_url":             "http://merchantsite.com/products/awesome-pants.html"
      },
      {
        "display_name":         "Best Drone",
        "sku":                  "DEF-456",
        "unit_price":           5999,
        "qty":                  1,
        "item_image_url":       "http://merchantsite.com/images/best-drone.jpg",
        "item_url":             "http://merchantsite.com/products/best-drone.html"
      }]
display_name
required object. The display name of the product.
sku
required string. The product SKU.
unit_price
required integer. The item price expressed as integer USD cents ("$100" = 10000).
qty
required integer. The item quantity expressed as an integer.
item_image_url
required string. The item's product image URL.
item_url
required string. The item's product description page URL.

 

Sending the checkout request

With the checkout object built, you can now call:

affirm.checkout.post();

This method will send a POST request to the /checkout/ API endpoint with the checkout object as the data payload. Then, it will redirect the user to the Affirm checkout flow on the affirm.com domain.

Syntax notes
  • The checkout object is sent as a JSON object.
  • All numerical values must be sent as integer USD cents ($25.00 -> 2500).
  • The items are stored in an object array. You should build this array dynamically by adding item objects to it based on cart contents.
  • The discount object uses the discount code as the name of the nested objects. As a result, you may have to construct each discount without the use of a strongly-typed class.
Checkout object validation

The following data in the checkout object is validated:

  • Name
    • There must be a first and last name.
  • Address
    • The address must have a direct match on both Smarty Streets and Google Maps.
  • Phone number
    • Number must be a valid US cell phone number that is able to receive SMS text messages.
  • Total
    • An order total must be present and greater than 0.
  • Discount
    • Any discount values must be positive integers.
  • Item
    • Item URL   
      • Must be present, but can be an empty string.
Error handling

Errors generated by the checkout request are presented on the page where checkout is initiated, in the form of a pop-up modal window. Specific messaging about the source of the error is presented in this modal (e.g., "Invalid phone number"). 

You may define a callback function when this error modal is closed, but currently that callback does not relay any event data specific to the error message that's displayed in the modal. 

Here's an example of how this event callback would be defined:

affirm.ui.ready(
    function() {
        affirm.ui.error.on("close", function(){
            alert("Please check your contact information for accuracy.");
        });
    }
);


Receive Checkout Token

Summary

After a user has successfully completed the Affirm checkout flow, the customer is returned to the "user_confirmation_url" that is provided to Affirm in the checkout object. Affirm will POST a "checkout_token" to this endpoint. This is the token used to Authorize a particular charge, completing the checkout. 

Authorization flow
  1. User successfully completes an Affirm checkout & confirms their loan.
  2. User is redirected from Affirm.com to the user_confirmation_url via the HTTP method defined by user_confirmation_url_action 
  3. The HTTP request to the user_confirmation_url contains the checkout_token in the request parameters.
  4. The page at the user_confirmation_url reads the request form and temporarily stores this checkout_token.
  5. The page at the user_confirmation_url sends a POST request to the Affirm API authorization endpoint (/api/v2/charges/) with the saved checkout_token.
  6. The page at the user_confirmation_url expects a response from the Affirm API with the charge information
  7. The page at the user_confirmation_url validates that the authorized amount is equal to the order total and that the Order_ID matches the order
  8. If the amount and order_id are valid, the page at the user_confirmation_url stores the 'id' from the returned charge object. This Charge ID is attached to the order; and is used to uniquely identify the order. All future charge actions require this identifier.
  9. Order is created.
  10. Customer is presented with order confirmation page/message.
Define the user_confirmation_url

When assembling the checkout object, you will have to define a user_confirmation_url. This URL should point to your page that is expecting the checkout_token and then attempts charge authorization.

The merchant object contains the user_confirmation_url and user_cancel_url, which represent the two possible outcomes of the checkout attempt. The user goes to the confirmation_url if the user is approved and confirms their loan. The user goes to the cancel_url in all other cases (voluntary cancel, credit decline, identity verification issue, etc.). 

"merchant": {
    "user_confirmation_url":    "https://merchantsite.com/confirm",
    "user_cancel_url":          "https://merchantsite.com/cancel",
    "user_confirmation_url_action": "POST", // or "GET"
    "name":          "External Company Name"
     },
user_confirmation_url
required url. URL that the customer is sent to if they successfully complete the Affirm checkout flow. 
A checkout_token will be sent to this URL in the POST request, and that checkout_token should be used to authorize the charge before the user is redirected to the order confirmation page.
Analytics tags are other query string parameters can be persisted here as well. Read more here.
user_cancel_url
required url. URL that the customer is sent to if the customer exits the Affirm checkout flow.
This is the same if the user voluntarily cancels or closes the window before completion, or if the user is denied. You should setup the cancel_url to be the checkout payment page, and you can also append analytics tags to the URL to help you identify who you may want to reach out to about alternative payment methods or reapplying. 
Analytics tags are other query string parameters can be persisted here as well. Read more here.
user_confirmation_url_action
optional string. Accepted values are: 'GET', 'POST'. Defaults to 'POST'. Read more here.
name
optional string. If you have multiple sites operating under a single Affirm account, you can override the external company/brand name that the customer sees. This affects all references to your company name in the Affirm UI.

Confirmation page logic

The logic on your user_confirmation_url should be as follows:

  1. Expect checkout_token in HTTP request parameters
  2. Use checkout_token to make an authorization request to Affirm's API
    • If successful (200) response:
      • Validate that authorized amount equals the order total
        • If authorized amount is valid
          • Redirect user to order confirmation page or display order confirmation message.
          • Store charge ID.
          • Mark order payment as pending.
        • If authorized amount is invalid
          • Message to the user that the payment failed
          • Redirect user to payment method selection screen in the checkout flow
    • If error (non-200) response (edge case):
      • Message to the user that the payment failed
      • Redirect user to payment method selection screen in the checkout flow
Receive the checkout_token

To receive the checkout_token, you will have to setup your page with server-side scripting that reads the HTTP request parameters. This can be accomplished using any server-side scripting language, such as PHP, ASP, Perl, Ruby, etc. For more specific instructions based on your web application language, please contact mts@affirm.com for help.


Authorize a charge

POST /api/v2/charges
Summary

Charge authorization occurs after a user has successfully completed the Affirm checkout flow and returns back to the merchant site. Authorizing the charge generates the charge ID that will be used to reference this charge moving forward. A charge is not fully created before being authorized, and thus is not visible in the 'read charge' response, nor in the User/Merchant Dashboard.

Authorization request

curl https://sandbox.affirm.com/api/v2/charges
     -X POST
     -u "<public_api_key>:<private_api_key>"
     -H "Content-Type: application/json"
     -d '{"checkout_token": "<checkout_token>","order_id": "JKLM4321"}'
Options
  • Type: POST
  • Authorization: Basic
  • Content type: application/JSON
  • Data: JSON string
Data
checkout_token
required string. Unique token used to authorize a charge. Received to the user_confirmation_url
order_id
optional string. Identifies the order within the merchant's order management system that this charge corresponds to.

Authorization response

The response to your request will contain the full charge response object, which includes all of the information that was submitted when you initialized checkout in addition to the charge and transaction-level identifiers.

The only two pieces of information you need to parse from this charge response object are the 'amount' and the charge 'id' (highlighted below):

{
   "id:ALO4-UVGR",
   "created":"2016-03-18T19:19:04Z",
   "currency":"USD",
   "amount":6100,
   "auth_hold":6100,
   "payable":0,
   "void":false,
   "expires": "2016-04-18T19:19:04Z",
   "order_id":"JKLM4321",
   "events":[
      {
         "created":"2014-03-20T14:00:33Z",
         "currency":"USD",
         "id":"UI1ZOXSXQ44QUXQL",
         "transaction_id":"TpR3Xrx8TkvuGio0",
         "type":"auth"
      }
   ],
   "details":{
      "items":{
         "sweater-a92123":{
            "sku":"sweater-a92123",
            "display_name":"Sweater",
            "qty":1,
            "item_type":"physical",
            "item_image_url":"http://placehold.it/350x150",
            "item_url":"http://placehold.it/350x150",
            "unit_price":5000
         }
      },
      "order_id":"JKLM4321",
      "shipping_amount":400,
      "tax_amount":700,
      "shipping":{
         "name":{
            "full":"John Doe"
         },
         "address":{
            "line1":"325 Pacific Ave",
            "city":"San Francisco",
            "state":"CA",
            "zipcode":"94112",
            "country":"USA"
         }
      }
      "discounts": {
        "RETURN5": {
          "discount_amount":    500,
          "discount_display_name": "Returning customer 5% discount"
        },
        "PRESDAY10": {
          "discount_amount":    1000,
          "discount_display_name": "President's Day 10% off"
        }
      }
   }
}
  • id
  • created
  • currency
  • amount
  • auth_hold
  • payable
  • void
  • order_id
  • events
    • created
    • currency
    • id
    • transaction_id
    • type
  • details
    • items
      • product sku
        • sku
        • display_name
        • qty
        • item_type
        • item_image_url
        • item_url
        • unit_price
    • order_id
    • shipping_amount
    • tax_amount
    • shipping
      • name
        • full
      • address
        • line1
        • line2
        • city
        • state
        • zipcode
        • country
    • billing
      • name
        • full
      • address
        • line1
        • line2
        • city
        • state
        • zipcode
        • country
    • discounts
      • discount code
        • discount_amount
        • discount_display_name

 

  • Validate that the authorized amount equals the order total amount
  • If amount is valid, store the (charge) 'id' to reference the charge when performing the various charge actions: capture, void, refund, and update.
Authorization error handling

If the authorization request fails for some reason, you will setup error handling to block order creation and direct the user back to payment method selection.

Error HTTP status Message to display Action to take
Authorization failed 400 "There was an issue authorizing your Affirm loan. Please check out again or use a different payment method." Redirect user back to payment method selection.
Unauthorized 401 "There was an issue authorizing your Affirm loan. Please check out again or use a different payment method." Redirect user back to payment method selection.
Checkout_token expired 401 "There was an issue authorizing your Affirm loan. Please check out again or use a different payment method." Redirect user back to payment method selection.

 


Charge States

 

Status Description Actions triggered Available Charge Actions
Authorized

The charge has been authorized and a charge_id is provided in the authorization response to reference this charge moving forward.

The authorization will expire after 30 days (default).

  • Charge ID is generated
  • User receives a message:
    "Thanks for using Affirm! Once (merchant name) has processed your order, we'll send your first payment invoice. Check status at http://www.affirm.com/u"
  • Charge is now visible in the Merchant Dashboard
Capture, Void, Read, Update
Voided

The charge has been voided, or the authorization has expired, and no further actions can be taken.

  • User receives a message
Read
Captured

The charge has been captured and the merchant will receive their funds. The user will begin payments 30 days after the capture.

 

  • User receives a message:
    "Affirm charge confirmed for (amount) at (merchant). View more details and pay your bills at https://www.affirm.com/account"
  • Affirm transfers funds to merchant within 2-3 business days
  • Affirm sends invoice to customer for the first payment, due in 30 days.
Refund, Read, Update
Partially Refunded The charge has been partially refunded and there is still a positive balance on the loan.
  • User receives a message:
    "Affirm refund confirmed for (amount) from (merchant). View more details at https://www.affirm.com/account"
  • Affirm will withhold refunded amount from next settlement
Refund, Read, Update
Refunded The charge has fully refunded and there is a zero balance on the loan.
  • User receives a message:
    "Affirm refund confirmed for (amount) from (merchant). View more details at https://www.affirm.com/account"
  • Affirm will withhold refunded amount from next settlement
Read


Charge Actions

The charge actions described on this page should all be integrated into your back-end order management system, where you would normally be fulfilling orders and processing payments/refunds/cancelations.

 

Read

GET /api/v2/charges/<charge_id>
  • Read the charge information for a specific charge, or all charges
  • Returns all of the checkout data along with current charge status
    • Status: authorized/captured/voided/refunded/partially-refunded
  • Useful for updating your records or OMS with the current state of a charge before charge actions are performed
  • Can keep your system in sync with Affirm if your staff will be manually managing loans in the Merchant Dashboard
Read request

Read a single charge: 

curl https://sandbox.affirm.com/api/v2/charges/CHARGE_ID/
     -X GET
     -u "public_key:private_key"

 

Read multiple charges: 

curl https://sandbox.affirm.com/api/v2/charges/?limit=5&before=1234-ABCD
     -X GET
     -u "public_key:private_key"

 

URL

 

If no <charge_id> is specified,  a list of charges will be returned, and you can define how the results are paginated using the query string parameters below:

Query String
limit
optional integer. Number of charges to be included in the response
before
optional string. Returns a list of charges that were created before the given charge ID.
after
optional string. Returns a list of charges that were created after the given charge ID.

Read response

{
   "id:ALO4-UVGR",
   "created":"2016-03-18T19:19:04Z",
   "currency":"USD",
   "amount":6100,
   "auth_hold":6100,
   "payable":0,
   "void":false,
   "expires": "2016-04-18T19:19:04Z",
   "order_id":"JKLM4321",
   "events":[
      {
         "created":"2014-03-20T14:00:33Z",
         "currency":"USD",
         "id":"UI1ZOXSXQ44QUXQL",
         "transaction_id":"TpR3Xrx8TkvuGio0",
         "type":"auth"
      }
   ],
   "details":{
      "items":{
         "sweater-a92123":{
            "sku":"sweater-a92123",
            "display_name":"Sweater",
            "qty":1,
            "item_type":"physical",
            "item_image_url":"http://placehold.it/350x150",
            "item_url":"http://placehold.it/350x150",
            "unit_price":5000
         }
      },
      "order_id":"JKLM4321",
      "shipping_amount":400,
      "tax_amount":700,
      "shipping":{
         "name":{
            "full":"John Doe"
         },
         "address":{
            "line1":"325 Pacific Ave",
            "city":"San Francisco",
            "state":"CA",
            "zipcode":"94112",
            "country":"USA"
         }
      }
      "discounts": {
        "RETURN5": {
          "discount_amount":    500,
          "discount_display_name": "Returning customer 5% discount"
        },
        "PRESDAY10": {
          "discount_amount":    1000,
          "discount_display_name": "President's Day 10% off"
        }
      }
   }
}
  • id
  • created
  • currency
  • amount
  • auth_hold
  • payable
  • void
  • order_id
  • events
    • created
    • currency
    • id
    • transaction_id
    • type
  • details
    • items
      • product sku
        • sku
        • display_name
        • qty
        • item_type
        • item_image_url
        • item_url
        • unit_price
    • order_id
    • shipping_amount
    • tax_amount
    • shipping
      • name
        • full
      • address
        • line1
        • line2
        • city
        • state
        • zipcode
        • country
    • billing
      • name
        • full
      • address
        • line1
        • line2
        • city
        • state
        • zipcode
        • country
    • discounts
      • discount code
        • discount_amount
        • discount_display_name

 

Capture

POST /api/v2/charges/<charge_id>/capture

This captures the funds of an authorized charge, and is the same as capturing a typical credit card transaction.  

Once a loan is captured:

  • User receives a notice that the charge is captured.
  • User's first payment is due to Affirm in 30 days.
  • Affirm pays the merchants within 2-3 business days.
  • Full or partial refunds can be processed within 120 days.
Capture request

curl https://sandbox.affirm.com/api/v2/charges/CHARGE_ID/capture
     -X POST
     -u "(public_api_key):(private_api_key)"
     -H "Content-Type: application/json"
     -d '{"order_id": "JKLM4321", "shipping_carrier": "USPS", "shipping_confirmation": "1Z23223"}'
URL
Data
order_id
optional string. Your internal order id. This is stored for your own future reference.
shipping_carrier
optional string. The shipping carrier used to ship the items in the charge.
shipping_confirmation
optional string. The tracking number for the shipment.

Capture response

{
    "fee": 600,
    "created": "2016-03-18T00:03:44Z",
    "order_id": "JKLM4321",
    "currency": "USD",
    "amount": 6100,
    "type": "capture",
    "id": "O5DZHKL942503649",
    "transaction_id": "6dH0LrrgUaMD7Llc"
}
fee
integer. Portion of the captured amount that represents the merchant fee.
created
string. Timestamp for this event.
order_id
string. The order ID in your order management system.
amount
integer. Amount captured, including any fees.
type
string. Will always be "capture".
id
string. The ID for this API event.
transaction_id
string. The ID for the charge transaction.

 

Capture error handling

Error HTTP status Message to display Action to take
Captured failed 400    
Unauthorized 401    
Authorization expired 401    

Void

POST /api/v2/charges/<charge_id>/void

This cancels an authorized charge. For example, when a user decides to cancel their order before it's fulfilled.

Once a loan is voided:

  • It is permanently canceled and cannot be reauthorized.
  • User receives a notice that the transaction is canceled.
Void request

curl https://sandbox.affirm.com/api/v2/charges/CHARGE_ID/void
     -X POST
     -u "(public_api_key):(private_api_key)"
URL

Void response

{
  "type": "void",
  "id": "N5E9OXSIDJ8TKZZ9",
  "transaction_id": "G9TqohxBlRPWTGB2",
  "created": "2014-03-17T22:52:16Z",
  "order_id": "JLKM4321"
}
type
string. Always 'void'.
id
string. ID for this API event.
transaction_id
string. Transaction ID for this charge event.
created
string. Timestamp for this event.
order_id
optional string. Your internal order ID.

 

Void error handling

Error HTTP status Message to display Action to take
Authorization failed 400    
Unauthorized 401    
Checkout_token expired 401    

 

Refund

POST /api/v2/charges/<charge_id>/refund
  • You can apply any amount of refunds on a charge so long as there is a positive balance on the loan. 
  • Once a loan is fully refunded it cannot be reinstated.
  • Refunds can only be applied within 120 days of capturing the charge.
  • The amount you refund is based upon the original purchase price, just as if it was a normal credit card transaction. Interest and fees corresponding to the refunded amount are all automatically calculated on Affirm's end.
Refund request

curl https://sandbox.affirm.com/api/v2/charges/CHARGE_ID/refund \
     -X POST
     -u "(public_api_key):(private_api_key)"
     -H "Content-Type: application/json"
     -d '{"amount": 500}'
URL
Data
amount
optional string. The amount to be refunded. If this parameter is missing or null, then by default the remaining loan balance will be refunded.

Refund response

{
  "created": "2014-03-18T19:20:30Z",
  "fee_refunded": 15,
  "amount": 500,
  "type": "refund",
  "id": "OWA49MWUCA29SBVQ",
  "transaction_id": "r86zdkHONPcaiVJJ"
}
created
string. Timestamp for this event.
fee_refunded
integer. Portion of the refunded amount that is subtracted from the merchant fee.
amount
integer. Amount refunded, including any fees.
type
string. Will always be "refund".
id
string. ID for this API event.
transaction_id
string. ID for this charge event.

 

Refund error handling

Error HTTP status Message to display Action to take
Authorization failed 400    
Unauthorized 401    
Checkout_token expired 401    

 

Update

POST /api/v2/charges/<charge_id>/update
  • Update a charge with new shipping, order information or shipping address
    • Shipment tracking number
    • Shipping carrier
    • Order ID
    • Shipping address
  • Shipping information is used by the Affirm customer service staff to see the fulfillment/delivery status of an order
  • Order ID is used in reconciliation reports and other places where Affirm charges need to be associated with internal order IDs
  • Shipping address is used to validate and update the shipping address in Affirm after the order is placed. If shipping address provided in the update request fails validation, an error is returned and the shipping address is not updated.
Update request

curl https://sandbox.affirm.com/api/v2/charges/CHARGE_ID/update
     -X POST
     -u "(public_api_key):(private_api_key)"
     -H "Content-Type: application/json"
     -d '{"order_id": "JLKM4321", "shipping_carrier": "USPS", "shipping_confirmation": "1Z23223", "shipping": {"name":{ "full": "John Doe"},"address": {"line1": "325 Pacific Ave", "state": "CA", "city": "San Francisco", "zipcode": "94111", "country": "USA"}}}'
URL
Data
order_id
optional string. Your internal order ID
shipping_carrier
optional string. The shipment carrier (e.g., "UPS").
shipping_confirmation
optional string. The shipment tracking number.
shipping
optional object. Customer shipping information.
 

Update response

{  
   "created":"2016-11-30T21:07:47Z",
   "order_id":"JLKM4321",
   "shipping_confirmation":"1Z23223",
   "shipping":{  
      "name":{  
         "full":"John Doe"
      },
      "address":{  
         "city":"San Francisco",
         "state":"CA",
         "zipcode":"94111",
         "line1":"325 Pacific Ave",
         "country":"USA"
      }
   },
   "shipping_carrier":"USPS",
   "type":"update",
   "id":"EILMLQLZPGC742HO"
}
created
string. Timestamp for this event.
id
string. ID for this API event.
order_id
optional string. Your internal order ID.
shipping_carrier
optional string. Shipment carrier (e..g, 'UPS').
shipping_confirmation
optional string. Shipment tracking number. 
shipping
optional object. Customer shipping address information.
 


Testing

Sandbox transactions
  1. Once you initiate checkout, you'll see the account creation screen.
    • If you've already created an account, click the 'Log In' button
    • If you haven't created an account, create one now.
      • Any First and last name
      • Valid email address format
      • Valid (random) US cell phone number
      • Birthdate longer than 18 years ago
      • Any four digits
  2. You'll be asked to enter a PIN number, use '1234'. We do not text you a PIN number in the Sandbox environment
  3. You will always see 3, 6, and 12 month terms.
  4. Once you click the 'Confirm' button, you'll be redirected to the user_confirmation_url with the checkout_token.
Live transactions
  • Do not use your own personal account to do test transactions in the Affirm live environment
  • Affirm furnishes loan and repayment information to credit bureaus. Capturing arbitrary test loans could impact your actual credit score.
  • Please engage merchanthelp@affirm.com to coordinate tests in the live environment.


Error Messages

auth-declined
Charge authorization hold declined.
capture-greater-instrument
Charges on this instrument cannot be captured for more than the authorization hold amount.
capture-unequal-instrument
Charges on this instrument cannot be captured for an amount unequal to authorization hold amount.
capture-voided
Cannot capture voided charge.
partial-capture-instrument
Charges on this instrument cannot be partially captured.
refund-exceeded
Max refund amount exceeded.
refund-uncaptured
Cannot refund a charge that has not been captured.
refund-voided
Cannot refund voided charge.
capture-declined
Charge capture declined.
capture-limit-exceeded
Max capture amount on charge exceeded.
expired-authorization
Cannot capture expired charge authorization hold.
refund-expired
Charges on this instrument must be refunded within N days of capture.
financial-product-invalid
Please provide a valid financial product key.
invalid_field
An input field resulted in invalid request.
public-api-key-not-specified
Please provide a public API key.
public-api-key-invalid
Please provide a valid public API key.
public-api-key-wrong-environment
Please provide a live public API key when not using the sandbox environment.
public-api-key-inactive
Please provide an active public API key.
api-key-pair-not-specified
Please provide a API key pair.
private-api-key-invalid
Please provide a valid private API key.
api-key-pair-wrong-environment
Please provide a live API key pair when not using the sandbox environment.
api-key-pair-inactive
Please provide an active API key pair.
not_found
The resource(s) specified in the request could not be found.


Logging

Merchant Dashboard

The Sandbox and Live Merchant Dashboard displays:

  • API calls
  • Authorized charges
API Calls
  • /checkout/
    • Initiates checkout.
    • 200 response indicates that the user was redirected to Affirm to complete the checkout
  • /charges/
    • Authorizes charges.
    • 200 response indicates the charge was authorized
  • /charges/<charge_id>
    • Reads charges
  • /charges/<charge_id>/capture
    • Captures the charge
    • 200 response indicates the action was completed successfully
  • /charges/<charge_id>/void
    • Voids an authorized charge
    • 200 response indicates the action was completed successfully
  • /charges/<charge_id>/refund
    • Refunds a captured charge
    • 200 response indicates the action was completed successfully
  • /charges/<charge_id>/update
    • Updates a charge with new shipping information
    • 200 response indicates the action was completed successfully


Example Code

Example Integrations

To show how the server-side API calls are performed using various server-side scripting languages, we have the following examples available:

PHP affirm-php.zip
ASP.NET 4.5 WebForms (C#) asp-wf.zip
ASP Classic (ASP Script) asp_classic-asp_script.zip
Java affirm-java.zip
Initiating Checkout

Charge Authorization
<?
php $checkout_token = $_REQUEST['checkout_token'];
        
//These are sandbox credentials
// $public_key = "ARQBLCL7NAMBTZ7F"; 
// $private_key = "RkHBmVSP5ayC2rCUujwhArpGWPxpuTtv";
//This is the sandbox API URL
// $url = "https://sandbox.affirm.com/api/v2/charges/";

$data = array("checkout_token" => $checkout_token);
$json = json_encode($data);
$header = array('Content-Type: application/json','Content-Length: ' . strlen($json));

$keypair = $public_key . ":" . $private_key;

$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);                                                                     
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_USERPWD, $keypair);
curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

curl_close($curl);

http_response_code($status);
echo $response;
?>