Skip to main content

Merchant Help

 

Affirm Merchant Help

Direct API beta

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

 

Overview

Integration Points
  • Product and Cart pages
    • Promotional messaging and educational modals added.
       
  • 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.open()' 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 the 'id'
  15. Merchant redirects user to order confirmation page
  16. Order is complete


Retrieve your API keys from the merchant dashboard

How to access your Affirm merchant account credentials.
Google Account

You can sign into the Affirm Dashboard using Google, or using your email and password.

  • If you'd like to use the Google sign-in option, and your work 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 select your work account after clicking the Google sign-in button.

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. Sign in with Google, or use your email and password.

Note: The work email address that you use to sign-in to the Affirm Dashboard must be granted access by your Dashboard's administrator, or your Affirm contact.

Need help accessing the Affirm Dashboard?

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


Embed Affirm.js

Add the Affirm.js embed code to the head of your global page template.

<!-- Affirm -->
<script>
 _affirm_config = {
   public_api_key:  "YOUR_PUBLIC_KEY",
   script:          "https://cdn1-sandbox.affirm.com/js/v2/affirm.js",
   session_id:      "YOUR_VISITOR_SESSION_ID"
 };
 (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>
<!-- End Affirm -->

Note: Replace public_api_key with your public API key found in the merchant dashboard. The API key must match the Affirm-environment you're referencing ('sandbox' or 'live'). You can also pass a session ID variable for the optional session_id to take advantage of additional analytics.

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.open() - 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:  "YOUR_PUBLIC_KEY",
    script:          "https://cdn1-sandbox.affirm.com/js/v2/affirm.js"
    session_id:      "YOUR_VISITOR_SESSION_ID"
  };

Checkout object

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":"Joe",
          "last":"Doe"
          // You can include the full name instead
          // "full" : "John Doe"
        },
        "address":{
          "line1":"633 Folsom St",
          "line2":"Floor 7",
          "city":"San Francisco",
          "state":"CA",
          "zipcode":"94107",
          "country":"USA"
        },
        "phone_number": "4153334567",
        "email": "joedoe@123fakestreet.com"
      },
      "billing":{
        "name":{
          "first":"Joe",
          "last":"Doe"
        },
        "address":{
          "line1":"633 Folsom St",
          "line2":"Floor 7",
          "city":"San Francisco",
          "state":"CA",
          "zipcode":"94107",
          "country":"USA"
        },
        "phone_number": "4153334567",
        "email": "joedoe@123fakestreet.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"
        "categories": [
            ["Home", "Bedroom"],
            ["Home", "Furniture", "Bed"]
        ],
      "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": {
          //webhook_session_id:
          //user defined key/value pairs
      },

      "order_id":               "JKLMO4321",

      "shipping_amount":        1000,
      "tax_amount":             500,
      "total":                  5997
  });
 
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.
Note: We only use this value for the loan total; we do not calculate the total from the checkout object line items.
   
   

 

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. 
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": "John",
   "last": "Doe",
   "full": "John Doe"
}
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",
        "categories": [
            ["Apparel", "Pants"],
            ["Mens", "Apparel", "Pants"]
        ]
      },
      {
        "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",
        "categories": [
            ["Electronics", "Drones"],
            ["Drones", "Best Drones"]
        ]
      }]
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.
categories
optional array. An array of lists that indicate the various categories that apply to this product, and the hierarchy of those category definitions. Each list in the array contains one or more comma-separated strings, with the first string being the highest-level (widest) category.

 

Metadata object

 "metadata": {
        "shipping_type":        "UPS Ground",
        "entity_name":          "internal-sub_brand-name",
        "platform_type":        "your-platform-name",
        "webhook_session_id":        "A1b2C3"
      },
shipping_type
required string. Customer contact information.
entity_name
optional string. Internal sub-brand name. 
platform_type
optional string. Name of your platform Ex: Magento.
webhook_session_id
optional string. Customer or session specific ID that's used to reconcile incoming webhooks.

 


Initiate checkout

Initiating checkout

Redirect

With the checkout object built, you can now call:

affirm.checkout.open();

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(){
            console.log("Affirm modal closed");
        });
    }
);


Receive checkout token

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 GET/POST 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 the 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
disputed A dispute has been opened and the charge is essentially refunded.   None
dispute_refunded A dispute has been resolved in the customer's favor and the refund stays in effect.   None

 


Setup order management functions

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 Checkout

GET /api/v2/checkout/<checkout_id>
  • checkout_id is the same string as the checkout_token
  • Read the checkout information for a specific checkout attempt
  • Returns all of the checkout data along with current checkout status
    • Status: opened/confirmed
  • Useful for updating your phone or instore agent's UI
Read request

 

curl https://sandbox.affirm.com/api/v2/checkout/CHECKOUT_ID/
     -u "public_key:private_key"
URL
checkout_id
required string. Also known as the checkout_token. This ID is returned in the direct checkout API response.

 

Read response

{
   "status": "opened",
   "created":"2016-03-18T19:19:04Z",
   "currency":"USD",
   "total":6100,
   "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":"633 Folsom St",
            "line2":"Floor 7",
            "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"
        }
      }
   }
}
  • status
  • created
  • currency
  • total
  • 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

Read Charge

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",
   "status": "auth",
   "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":"633 Folsom St",
            "line2":"Floor 7",
            "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
  • status
  • 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", "transaction_id": "A1B2C3}'
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.
transaction_id
optional string. Your internal transaction ID. This is stored in our platform and associated with this charge event. This transaction ID will appear in the charge response object and settlement reports.

Capture response

{
    "fee": 600,
    "created": "2016-03-18T00:03:44Z",
    "order_id": "JKLM4321",
    "currency": "USD",
    "amount": 6100,
    "type": "capture",
    "id": "O5DZHKL942503649",
    "transaction_id": "6dH0LrrgUaMD7Llc",
    "merchant_transaction_id": "A1B2C3"
}
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.
merchant_transaction_id
optional string. Your internal transaction ID that was sent with the capture request. This transaction ID will appear in the charge response object and settlement reports.

 

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": 50000, "merchant_transaction_id": "A1B2C3"}'
URL
Data
amount
optional integer. The amount to be refunded in USD cents ($500 = 50000). If this parameter is missing or null, then by default the entire remaining loan balance will be refunded (full refund).
merchant_transaction_id
optional string. Your internal transaction ID. This is stored in our platform and associated with this charge event. This transaction ID will appear in the charge response object and settlement reports.

Refund response

{
  "created": "2014-03-18T19:20:30Z",
  "fee_refunded": 1500,
  "amount": 50000,
  "type": "refund",
  "id": "OWA49MWUCA29SBVQ",
  "transaction_id": "r86zdkHONPcaiVJJ",
  "merchant_transaction_id": "A1B2C3"
}
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.
merchant_transaction_id
optional string. Your internal transaction ID that was sent with the refund request. This transaction ID will appear in the charge response object and settlement reports.

 

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 fulfillment, or order information.
    • Shipment tracking number
    • Shipping carrier
    • Order ID
  • Order ID is used in settlement reports and other places where Affirm charges need to be associated with internal order IDs
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.
 

Add the confirmation page function

When a customer completes their purchase, you can send their order and product information to Affirm for A/B testing, which will help you optimize your site. Send this information by adding the Confirmation Page function to your payment confirmation page. We only require orderId, total, productId, and quantity for A/B testing.

Click here for all the Confirmation Page function parameters.

affirm.analytics.trackOrderConfirmed({
    "orderId": "T12345",
    "total": 3739
}, [{
    "productId": "SKU-1234",
    "quantity": 1
}, {
    "productId": "SKU-5678",
    "quantity": 1
}]);

Required function parameters

Order object

Parameter Type Description
orderId string Your internal unique identifier representing the order. Maximum 500 characters.
total integer The total amount of the transaction, including tax and shipping, stated in USD cents (e.g., $100 = 10000).

Product object

Parameter Type Description
productId string Your internal unique identifier representing the product, such as the SKU or an internal database identifier. Maximum 500 characters.
quantity integer The quantity of the purchased product.

Test your integration

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 contact your Engagement Manager who is coordinating your launch, or merchanthelp@affirm.com to conduct 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;
?>