👷🏼‍♀️
Custom integration

Motivation

This guide assumes you wish to:
  • Charge customers on your site, using your existing e-commerce platform.
  • Let Awesound automatically fulfill each audio order, providing listeners with secure mobile access and tech support.
 
This guide assumes you have already set up your product on Awesound, and wish to bring the "charge customers" step in-house.
 
⚠️
This option requires manual setup. Email support@awesound.com to get started.
 

Setup process

If you're not using one of the supported platforms, or you prefer to roll your own API integration for any reason, that's no problem: we can work together to set up a custom API integration.
In most cases, there's no charge for this one-time setup, and implementation is relatively simple.
 
TIMELINE: Overall implementation time mainly depends on how long it takes you to prepare your API endpoint. For larger organisations, this is likely the main limiting factor. Once the API is ready for testing, we can complete the remaining steps on Awesound within a few days. We'll then run test purchases before going live.
 

The steps to launching your custom integration

  1. Create read-only API access so Awesound can fetch purchase details from your billing system.
  1. Create webhooks to inform Awesound of relevant events.
  1. At your end, each product will have a unique product ID. Save this product ID in Awesound.
  1. Customize the receipt email you send customers, to include a link their unique access on Awesound.
  1. Run some test purchases before launch.
 
🙌
If you are writing your API endpoints and webhooks from scratch, follow the structure below. If you have an existing API, or are constrained in the data or format you can expose, get in touch. We can write custom code at Awesound's end to parse your preferred payload structure.

1. Create read-only API access to orders

  • This is necessary to allow one-click links from the email YOU send customers, to directly access audio from Awesound
  • This also allows for troubleshooting / redundancy in the event of any failed webhooks from your platform, and ensures Awesound can have a live view of the order (e.g., in case the order was subsequently refunded).
For inspiration, see how API access works for WooCommerce, for Kartra and for BigCommerce.
 
Agree with Awesound:
  • Authentication method
    • For example, require header, {Authorization: Bearer API_TOKEN}
 
🔐
The exact security implementation will be agreed on a case-by-case basis and not detailed in this public guide. Similarly for inbound webhooks to work (Step 2), you will need to sign webhooks with your webhook secret.
 
Your endpoint should return a response (status 200) structured with the following keys:

REQUIRED

 
api_result
REQUIRED string
Value "success" if the API request is sensible and allowed, otherwise "fail".
If result is NOT "success", an "error" key should be present.
 
order_id
REQUIRED string
An integer is also acceptable. (It will be saved as a string on Awesound.)
 
order_status
REQUIRED string
Value must be one of "complete", "completed" or "paid". Otherwise, Awesound will ignore the event.
 
customer
REQUIRED object
Click to show child attributes
The customer object must contain the customer name and email. Other fields are optional.
  • email
    • REQUIRED string
  • name
    • OPTIONAL string
    • Required if first_name and last_name are not present.
  • first_name and last_name
    • OPTIONAL string in each case
    • If you collect Firstname Lastname separately in your checkout form, do populate first_name and last_name instead of just name. This will allow us to personalise email salutations without guessing the appropriate first name (e.g., "Dear Jane, …")
    • Required if name is not present.
  • email_verified
    • OPTIONAL string
    • Value trueor false. Set as trueif the user has already confirmed their email.
  • phone
    • OPTIONAL string
    • Spaces, brackets, dashes and periods are acceptable, but will be ignored. For example, 415.800.3881 or "(415) 800-3881" are both acceptable.
  • phone_country_dial_code
    • OPTIONAL string
    • +is optional. Acceptable values for USA include "1", "+1", "001".
  • phone_country_isocode
  • ip_address
    • OPTIONAL string
    • If included, this will help kick-start the piracy prevention tracking process for each customer. (Saving this can also help dispute chargeback requests.)
  • profile_picture_url
    • OPTIONAL string
  • metadata
    • OPTIONAL object
    • If you wish to save other custom information to Awesound, include it here.
If phoneis provided: one of phone_country_dial_code or phone_country_isocode should be provided for clarity. If phoneis provided but both phone_country_code and phone_country_isocodeare NOT provided, then the country is inferred with the following priority:
  1. Country in billing_details["country"], if a billing_details object is provided, and the countrykey is present.
  1. Country inferred from customer["ip_address"], if the ip_addresskey is present in the customer object.
  1. The default country saved to the publisher account.
If "phone" is provided, Awesound will text the customer with a handy link to listen on mobile. The alphanumeric sender name will be an 11-digit branded sender name to match the publisher's display name, e.g., "BLF Audio" or "Arora Medic".
 
Example customer object:
// Simplest possible customer object
"customer": {
  "name": "Jane Doe",          
  "email": "janedoe@gmail.com",
  "email_verified": false,
  "phone": "415 800 3881"
}


// More detailed customer object
"customer": {
  "first_name": "Jane", // Used in email receipt, e.g., "Dear Jane, …"         
  "last_name": "Doe",          
  "email": "janedoe@gmail.com",
  "email_verified": false,
  "phone": "4158003881",
  "phone_country_isocode": "US",
  "ip_address": "",     // Used for piracy prevention
}
 
 
items
REQUIRED list of objects
Click to show child attributes
The items bought should be a list of objects.
Each item object should contain the following keys:
  • product_id
    • REQUIRED string
  • product_name
    • REQUIRED string
  • amount_cents_paid
    • REQUIRED integer
  • price_cents_before_discount
    • OPTIONAL integer
    • Sticker price of product before any discount(s) applied.
  • item_discounts
    • OPTIONAL listof objects
    • Include only if customer has applied a coupon that does not apply to the whole order – e.g., 10% off this specific product. Otherwise, if one coupon has been applied to the entire order, you can instead populate the order-level order_discounts object.
    • Default value: []
    • Click to expand: child attributes
      • code
        • REQUIRED string
      • name
        • OPTIONAL string
      • percent_off
        • OPTIONAL integer
        • e.g., 10 for 10% off
      • amount_off_cents
        • OPTIONAL integer
        • e.g., 5000 for $50 off.
      For each discount, one of percent_off or amount_off_cents should be present.
      // Example code
      item_discounts: [
        { code: "10OFFSPRING",
          percent_off: 10,
          name: "Spring special"
        },
      ],
// Simplest possible items list, for a purchase with just one item
"items": [
  { "product_id": "47767",
    "product_name": "Test Prep Audio Revision",
    "amount_cents_paid": 16000
  }
]
 
currency
REQUIRED string
Three-letter currency code like "USD", "gbp", "EUR". (Upper/lower case does not matter.)
Default value if not provided: "USD".
 
amount_cents_paid
REQUIRED integer
This is the total for the order.
For example, 59900 for $599.
 

OPTIONAL

 
purchase_url
OPTIONAL string
This is the URL the customer was on when they bought the product.
Example: "https://example.com/products/test-prep-audio-review"
 
post_purchase_url
OPTIONAL string
If provided, customer may be invited to "view payment on example.com".
This will likely be private to the customer.
Example: "https://example.com/myacccount/order/123?confirmation=abcde"
 
amount_cents_before_discount
OPTIONAL integer
Order total before any discount applied.
For example, 69900 for $699.
 
billing_details
OPTIONAL object
  • address
    • OPTIONAL object
      Show child attributes
      If this object is present, country_isocode is expected. The following labels are recommended in order to be parsed by Awesound:
      • postal_code or zip_code
        • OPTIONAL string (strongly recommended)
        • Examples: "94103" (USA) or "SW1Y 4UH"(UK).
        • Either keyword, postal_code or zip_codeis acceptable. postal_code takes precedence.
      • state
        • OPTIONAL string (strongly recommended)
        • For US states, the value should be a two-letter abbreviation for US state ("CA", not "California" )
      • country
        • OPTIONAL string
        • Value as entered by the customer, e.g., "USA", "Ivory Coast" or "Côte d'Ivoire"
      • country_isocode
        • REQUIRED string if billing_details object is present
        • Value should be an alpha 2-code string like "US" (for United States), "CA"(Canada), "GB"(United Kingdom) or "AU"(Australia).
      • Other keys like name , address_line1, address_line2, address_line3 are acceptable, but will most likely be ignored by Awesound (not saved).
      This object will not be visible to the customer.
  • payment_method
    • OPTIONAL object
      Show child attributes
      • type
        • OPTIONAL string
          Expected values: "card", "paypal", "ach", "bank_transfer", "credit_note".
      • brand
        • OPTIONAL string
          Expected values: "Visa", "MasterCard", "American Express", "JCB", etc.
          Brand name can be capitalized, spelled out in full, and include spaces, e.g., "Visa", "Visa Debit", or "American Express"
          If provided, this may be visible to the customer and to you, in Awesound. (This can help with identifying card transactions, confirming refunds, or preventing chargeback disputes.)
      • last4
        • OPTIONAL string (of length four characters)
          Example value: "6772" without any preceding punctuation.
          If provided, this may be visible to the customer and to you, in Awesound. (This can help with identifying card transactions, confirming refunds, or preventing chargeback disputes.)
// Example value
"billing_details": {
  "address": {
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94103",
    "country_isocode": "US",
  },
  "payment_method": {
    "type": "card",
    "brand": "Visa",
    "last4": "6772"
  }
}
 
order_discounts
OPTIONAL listof objects
  • Include if customer has applied a coupon that applies to the whole order. Otherwise, see the item-specific item_discounts object.
Click to expand: child attributes
  • code
    • REQUIRED string
  • name
    • OPTIONAL string
  • percent_off
    • OPTIONAL integer
    • e.g., 10 for 10% off
  • amount_off_cents
    • OPTIONAL integer
    • e.g., 5000 for $50 off.
 
It is possible that the list of discounts could include more than one discount applied.
For each discount, one of percent_off or amount_off_cents should be present.
// Example value
order_discounts: [
  { code: "10OFFSPRING",
    percent_off: 10,
    name: "Spring special"
  },
]
 
metadata
OPTIONAL object
If there are any other details you wish to save to Awesound, include them here.
Recommended keys, at top-level, are:
utm_source, utm_campaign, utm_medium, utm_term, utm_content.
These five UTM parameters will be visible in your downloadable table of payments on Awesound.
All other metadata will be stored without being processed.
You can save any other information that may help with reporting later, e.g., sales_rep_name, test_purchase_ref, etc.
 
error (present only if API request fails)
OPTIONAL object, if order ID not found, or permission denied, or any other error processing the API request.
Click to show child attributes
  • message
    • REQUIRED string
      Human-readable explanation of the error, e.g., "Order not found"
  • code
    • OPTIONAL string
      Integer also accepted (will be saved as string on Awesound).
      Example value: "404"or "123".
 

Example JSON object

Click to show example API response object
// Example json response from https://api.example.com/v1/orders/123
{
  "api_result": "success",    // REQUIRED - "success" if order exists and permission to view
  "order_id": "123",    // REQUIRED string - integer also acceptable
  "order_status": "paid",     // REQUIRED string – Must be "complete", "completed" or "paid", or Awesound will ignore
  "customer": {...},    // REQUIRED object – See "customer" object above
  "items": [...],       // REQUIRED list of objects – See "items" above
  "purchase_url": ,     // OPTIONAL string – URL where product was bought. This should NOT be a private URL. The customer's email might include text, "Know someone who might like this? You can safely share this URL with a friend: ___".
  "post_purchase_url": "https://example.com/myacccount/order/123",
											  // OPTIONAL - URL on your site of an order confirmation page, if exists. 
  "billing_details": {...}, // OPTIONAL – object
  "amount_cents_paid": 999, // REQUIRED integer – Amount in cents, not dollars (e.g., 22000 for $220)
  "amount_cents_before_discount":  // OPTIONAL integer - 
  "discounts": [],      // OPTIONAL list – See "discounts" above
  "currency": "USD",    // REQUIRED - Three-letter uppercase currency code like 'USD', 'GBP', 'EUR'. Defaults to 'USD' if not supplied
}
 
Test your API endpoint
# Python example
# In development, test your endpoint with a GET request like this.
import requests
import json

AWESOUND_API_KEY = os.environ.get('AWESOUND_API_KEY') 

def get_order_json(order_number):
    url = "https://api.example.com/v1/orders/%s" % order_number
    headers= {"Authorization": "Bearer %s" % AWESOUND_API_KEY}
    resp = requests.get(url, headers=headers)
    if resp.status_code == 200:
        return resp.json() # or json.loads(resp.content) or json.loads(resp.text)
    else:
        print("Response code is %s" % resp.status_code)
        return None
 

2: Set up webhooks to POST event data to Awesound

Awesound will be notified of events such as order_succeeded, order_updated or refund.
 
Option 1: Include full payload data in webhook POST
The structure of the webhook should match the above, with one addition: include an "event_type"key to describe the type of event.
 
event_type
REQUIRED string
Value "order_created" or "order_updated or "refund".
You can use either "order_updated" or "refund" for refunds.
 
The error key will be absent.
 
All other keys and values should exactly match the API documentation in the previous step.
 
Option 2: Include limited data in webhook POST
In this case, the POST payload can be simple, including the event type and order_id. Upon receipt of the webhook, Awesound will ping your API to fetch the full details of the order.
 
Agree with Awesound staff which approach you wish to implement. Most customers with a WooCommerce / Zapier background choose Option 1. Sellers used to BigCommerce's API may gravitate towards option 2.
 

3: Save the product ID(s) to Awesound

Click "Edit", then save the product ID.
If this product is bought, Awesound will fulfill the order.
This allows you to simply POST a webhook to Awesound for all customer purchases. If a webhook event does not include a relevant product ID, the webhook will be ignored.

4: Customize the email you send to customers

This step is optional, and means that you can provide the customer with direct access to their personalized access waiting for them in Awesound.
In the receipt email, include the following link:
If you skip this step, that's fine; Awesound will email the customer with a link to their access.
(Reminder: If a phone number has been provided, Awesound will also text the customer with their unique access link.)
 

5: Make test purchases

You may wish to create a temporary (private) product page with a low-priced product, while running some test purchases.
Alternatively, consider using a discount coupon, so the amount charged to your card is just a few dollars. Better use a "95% off" coupon than a "100% off" coupon. It's good to run a few test purchases with real cards, and real transactions, to fully test the listener experience and collection of billing data.
 

Summary

Check-list of the steps involved

Prepare your API endpoint to respond to GET requests querying a particular order ID. This is most likely the only time-consuming step. Grant Awesound an API key to allow access; save this and the endpoint URL to your Awesound account.
Add an outbound webhook to POST a notification to Awesound when a relevant purchase has been made.
Save the relevant product ID(s) to your Awesound account, so Awesound knows which product purchases to look out for.
Finally, customize the receipt email you send to customers. If their receipt email contains a unique link containing both the order ID and customer email, Awesound can automatically redirect them to their personalized access page.
 

Your mileage may vary

The above is a recommended best-practice guide, based on successful implementation for tens of publishers with various custom requirements. An alternative setup can be arranged if your needs differ.
This is not a self-serve option; contact support@awesound.com when you're ready to take the first step.
 

The end result

  • You charge customers on your site – with bundles, discounts, custom pricing, your brand, etc.
  • Awesound "fulfills the order" – granting individual, secure, monitored access.
  • Most listeners will use mobile podcast apps they already use today – such as the podcast apps built and maintained by Apple and Google. Customers who buy audio products are often already familiar with their favorite podcast app.
    • If a customer is new to audiobooks, they're likely to simply listen in their browser. Our new mobile-friendly web player works beautiful on desktop, Android and iPhone, with auto-play next track, variable playback speed, etc.
    •  

Ready to get started?

Email support@awesound.com to begin.
Awesound