Connect Sub-Merchants To OptBlue

 

Now that you've constructed the Legal Entity and Account WePay API objects, you can indicate whether the sub-merchant is enrolled in AmEx's OptBlue program, and whether they would like to receive marketing content about the OptBlue program.

Remember:

The parameters listed here are the required parameters to onboard submerchants as a Payment Facilitator (PayFac). The API reference may indicate different requirements, but those requirements are the default, whereas PayFac requirements are enhanced.

Use the WePay Account ID in the POST /accounts/id endpoint to update their Account with this information:
Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/accounts/{WePay-Account-ID}' \
  -H 'App-Id: {Your-App-Id}'\
  -H 'App-Token: {Your-App-Token}'\
  -H 'Accept: application/json'\
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json' \
  --data-raw '{
    "incoming_payments": {
    "amex": {
      "program": {
        "opt_blue"
      },
      "countries": { 
        "US": {
           "opt_blue":{
               "opt_into_marketing": true
           }
        } 
      } 
    }
  }  
}'

Two things are achieved by executing the above API call:

  1. The sub-merchant is indicating that they are an AmEx OptBlue partner simply with the presence of the opt_blue object in program
  2. The sub-merchant is indicating that they are open to receiving marketing materials from AmEx when the value for opt_into_marketing is true (this is enabled as true by default)

Here is an example of what the API response may look like:

Copy
Copied
{
  "name": "Example Name",
  "description": "Example Description",
  "industry": {
    "merchant_category_code": "Example MCC",
    "category_detail": "Example Category"
    },
  "reference_id": "Custom reference number",
  "statement_description": "Example Statement Description",
  "projected_monthly_transaction_volume": null,
  "incoming_payments": {
    "accepted_methods": ["payment_bank", "visa", "mastercard", "american_express", "discover", "jcb", "diners_club"],
    "amex": {
      "program": "optblue",
      "countries": {
        "US": {
          "opt_blue": {
            "amex_seller_id": "Example Seller ID",
            "amex_seller_number": 1234567890,
            "opt_into_marketing": false,
            }
          }
        }
      }
    },
  "payout": {
    "default_currency": "USD",
    "currencies": {
      "USD": null
        }
      },
  "custom_data": null,
  "create_time": 1234567890,
  "balances": {
    "currencies": {}
      },
  "pricing": {
    "currencies": {
      "USD": {
        "credit_card": null,
        "payment_bank": null,
        "recurring_fee": null,
        "other_fees": {
          "debit_failure_fee": null
                }
              }
            }
          },
  "id": "{WePay-generated-UUID}",
  "resource": "accounts",
  "path": "/accounts/{WePay-generated-UUID}",
  "owner": {
    "id": "{WePay-generated-Legal-Entity-UUID}",
    "resource": "legal_entities",
    "path": "/legal_entities/{WePay-generated-Legal-Entity-UUID}"
        },
  "api_version": "3.0",
  "platform_onboarding_time": null,
  "beneficiary": {
    "id": "{WePay-generated-UUID}",
    "resource": "legal_entities",
    "path": "/legal_entities/{WePay-generated-UUID}"
          },
  "documents": []
}

Note that a sub-merchant can only be considered onboarded to AmEx OptBlue when a valid seller ID and number returns.

Handle OptBlue Response Files

In response to AmEx OptBlue onboarding requests, 2 files (Response file & Derog file) will be made available. To access these files, you'll first need to set up access to the SFTP server.

  1. Work with your integration team at WePay to get your unique public SSH keys (1 for production) from us
  2. Set up 1 SFTP server on default port 22; 1 for live use in production
  3. Provide the stage and production SFTP server host name and URLs to your integration team at WePay
  4. Optional: Generate a GPG key and provide the public key to your integration team at WePay
  5. Optional: Identify the server directory where you would like us to send response files. If none is identified, all files will be placed in the root directory

Onboarding Response File

The onboarding response file will contain any failures to onboard merchants to AmEx OptBlue for the previous day. This file will be uploaded within 48 hours.

The file will contain various merchant identifiers, including the seller ID and the WePay Account ID. There are two possible reasons that a merchant would be included in this file:

1. The merchant has been rejected by AmEx
In these cases, a reason will be present in the Data_Reject_Code_By_Amex column of the file indicating the field causing the rejection. Update the appropriate field in either a POST /accounts/id or a POST /legal_entities/id request.
Data_Reject_Code_By_AmexDescription
SDInvalid name on Account
SMInvalid industry.merchant_category_code on Account
SSInvalid address.line1 on Legal Entity
SNInvalid address.city on Legal Entity
SRInvalid address.region on Legal Entity
SPInvalid address.postal_code on Legal Entity
SCInvalid address.country on Legal Entity
SUInvalid currency, derived from address.country on Legal Entity
AXPlease contact us for details
2. AmEx accepted the merchant, but certain details must be updated
Use the following table to map column names to API fields, and fix the data in either a POST /accounts/id or a POST /legal_entities/id request.
Onboarding Failure File Column NameAPI resource & field
Entity details
Accounts_Name/accounts name
Accounts_Merchant_Category_Code/accounts industry.merchant_category_code
Accounts_Opt Blue_Opt into marketing/accounts incoming_payments.amex.countries.US.opt_blue.opt_into_marketing
Legal Entities_Entity_name/legal_entities entity_name
Legal Entities_Employee_identification_number/legal_entities entity_country_info.US.employer_identification_number
Legal Entities_Entity_Address_Line1/legal_entities address.line1
Legal Entities_Entity_Address_Line2legal_entities address.line2
Legal Entities_Entity_Address_City/legal_entities address.city
Legal Entities_Entity_Address_Region/legal_entities address.region
Legal Entities_Entity_Address_Postal_code/legal_entities address.postal_code
Legal Entities_Entity_Address_Country_code

Note: This field indicates that there is an issue with the account's currency, which is derived from the Legal Entity's country code
/legal_entities address.country
Legal Entities_Entity_Address_Phone_number/legal_entities phone.*
Legal Entities_Entity_Controller_Primary_url/legal_entities primary_url
Legal Entities_Entity_Address_country_code/legal_entities address.country
Legal Entities_Entity_Controller_Legal_form/legal_entities entity_country_info.US.legal_form
Legal Entities_Controller_enterprise_customer_id/legal_entities enterprise_customer_id
Controller details
Legal Entities_Entity_Controller_Email/legal_entities controller.email
Legal Entity_Controller_Firstname/legal_entities controller.name.first
Legal Entity_Controller_Lastname/legal_entities controller.name.last
Legal Entities_Controller_Date of birth/legal_entities controller.date_of_birth.*
Legal Entities_Controller_Address_Line1/legal_entities controller.address.line1
Legal Entities_Controller_Address_Line2/legal_entities controller.address.line2
Legal Entities_Controller_Address_City/legal_entities controller.address.city
Legal Entities_Controller_Address_Region/legal_entities controller.address.region
Legal Entities_Controller_Postal code/legal_entities controller.address.postal_code
Legal Entities_Controller_Country code/legal_entities controller.address.country
Additional Representative Details
Legal Entities_Additional representative1_First_name/legal_entities additional_representatives.representative_0.name.first
Legal Entities_Additional representative1_Last_name/legal_entities additional_representatives.representative_0.name.last
Legal Entities_Additional representative1_Social_security_number/legal_entities additional_representatives.representative_0.personal_country_info.US.social_security_number
Legal Entities_Additional representative1_Date_of_birth/legal_entities additional_representatives.representative_0.date_of_birth
Legal Entities_Additional representative1_Address_Line1/legal_entities additional_representatives.representative_0.address.line1
Legal Entities_Additional representative1_Address_Line2/legal_entities additional_representatives.representative_0.address.line2
Legal Entities_Additional representative1_Address_City/legal_entities additional_representatives.representative_0.address.city
Legal Entities_Additional representative1_Address_Region/legal_entities additional_representatives.representative_0.address.region
Legal Entities_Additional representative1_Address_Postal_code/legal_entities additional_representatives.representative_0.address.postal_code
Legal Entities_Additional representative1_Address_Country_code/legal_entities additional_representatives.representative_0.address.country
Legal Entities_Additional representative1_Address_Country_code/legal_entities additional_representatives.representative_0.address.country
Legal Entities_Additional representative2_First name/legal_entities additional_representatives.representative_1.name.first
Legal Entities_Additional representative2_Last name/legal_entities additional_representatives.representative_1.name.last
Legal Entities_Additional representative2_RepresentativeId/legal_entities additional_representatives.representative_1.reference_id
Legal Entities_Additional representative2_Date of birth/legal_entities additional_representatives.representative_1.date_of_birth.*
Legal Entities_Additional representative2_Address_Line1/legal_entities additional_representatives.representative_1.address.line1
Legal Entities_Additional representative2_Address_Line2/legal_entities additional_representatives.representative_1.address.line2
Legal Entities_Additional representative2_Address_City/legal_entities additional_representatives.representative_1.address.city
Legal Entities_Additional representative2_Address_Region/legal_entities additional_representatives.representative_1.address.region
Legal Entities_Additional representative2_Address_Postal code/legal_entities additional_representatives.representative_1.address.postal_code
Legal Entities_Additional representative2_Address_Country code/legal_entities additional_representatives.representative_1.address.country
Legal Entities_Additional representative3_First name/legal_entities additional_representatives.representative_2.name.first
Legal Entities_Additional representative3_Last name/legal_entities additional_representatives.representative_2.name.last
Legal Entities_Additional representative3_RepresentativeId/legal_entities additional_representatives.representative_2.reference_id
Legal Entities_Additional representative3_Date of birth/legal_entities additional_representatives.representative_2.date_of_birth.*
Legal Entities_Additional representative3_Address_Line1/legal_entities additional_representatives.representative_2.address.line1
Legal Entities_Additional representative3_Address_Line2/legal_entities additional_representatives.representative_2.address.line2
Legal Entities_Additional representative3_Address_City/legal_entities additional_representatives.representative_2.address.city
Legal Entities_Additional representative3_Address_Region/legal_entities additional_representatives.representative_2.address.region
Legal Entities_Additional representative3_Address_Postal code/legal_entities additional_representatives.representative_2.address.postal_code
Legal Entities_Additional representative3_Address_Country code/legal_entities additional_representatives.representative_2.address.country
Legal Entities_Additional representative4_First name/legal_entities additional_representatives.representative_3.name.first
Legal Entities_Additional representative4_Last name/legal_entities additional_representatives.representative_3.name.last
Legal Entities_Additional representative4_RepresentativeId/legal_entities additional_representatives.representative_3.reference_id
Legal Entities_Additional representative4_Date of birth/legal_entities additional_representatives.representative_3.date_of_birth.*
Legal Entities_Additional representative4_Address_Line1/legal_entities additional_representatives.representative_3.address.line1
Legal Entities_Additional representative4_Address_Line2/legal_entities additional_representatives.representative_3.address.line2
Legal Entities_Additional representative4_Address_City/legal_entities additional_representatives.representative_3.address.city
Legal Entities_Additional representative4_Address_Region/legal_entities additional_representatives.representative_3.address.region
Legal Entities_Additional representative4_Address_Postal code/legal_entities additional_representatives.representative_3.address.postal_code
Legal Entities_Additional representative4_Address_Country code/legal_entities additional_representatives.representative_3.address.country

Use Seller IDs and Numbers

The API response will contain the amex_seller_number and amex_seller_id parameters. Use those values when executing OptBlue transactions via Chase Merchant Services for that sub-merchant.

If the sub-merchant's preference for receiving marketing materials from AmEx ever changes, send another POST /accounts/id request for the appropriate sub-merchant with the new value for opt_into_marketing.

If the sub-merchant ever offboards from the OptBlue program, you must send another POST /accounts/id request for the appropriate sub-merchant with none as the value for program. The API request to update the WePay Account must be sent when the sub-merchant offboards from OptBlue.

Any subsequent requests making an update to any field in the WePay Account will result in an API Notification being sent to the accounts.updated event topic.

Offboard Sub-Merchants

If a sub-merchant ever offboards from the OptBlue program, you must send another POST /accounts/id request for the appropriate sub-merchant with none as the value for program instead of an object. The API request to update the WePay Account must be sent when the sub-merchant offboards from OptBlue.

This offboarding flow should be used for American Express blacklisted sub-merchants (identified in the Derog file) and for normal offboarding processes.

Below is an example request to offboard a sub-merchant from the OptBlue program:

Copy
Copied
curl -X POST \
  --url 'https://stage-api.wepay.com/accounts/{WePay-Account-ID}' \
  -H 'App-Id: {Your-App-Id}'\
  -H 'App-Token: {Your-App-Token}'\
  -H 'Accept: application/json'\
  -H 'Api-Version: 3.0'\
  -H 'Content-Type: application/json' \
  --data-raw '{
    "incoming_payments": {
     "amex": {
       "program": {
          "none"
          }
        }
    } 
}'

Next to Handle MATCH Results