Level 2 and Level 3 Data Processing

This page is dedicated to the passing of L2/L3 data in your transaction requests sent to Braintree for in-person transactions.

Feature Overview

The passing of L2/L3 transaction data can help lower interchange fee costs for eligible MCC codes and eligible card types. This is primarily relevant for merchants who provide products and services to other businesses in a B2B sales environment. More information about L2/L3 data processing can also be found at the general Braintree developer documentation site including instructions for configuring your tax ID on your Braintree merchant account.

Merchants who pass L2/L3 data will typically pass both L2 and L3 data in the same request. The below examples show the data being passed separately for example purposes only.

Level 2 Data Processing

Level 2 data is primarily tax information, and purchase order number. We allow for these data elements to be passed via the GraphQL API using the following input fields: purchaseOrderNumber, tax (with additional TransactionTaxInput) as seen in the below example of a card present charge request:

mutation RequestChargeFromInStoreReader($input: RequestChargeFromInStoreReaderInput!) {
    requestChargeFromInStoreReader(input: $input) {
        clientMutationId
        id
        status
        reader {
            id
            name                
            status
        }
    }
}

Once the transaction is completed on the reader you will need to perform your POS polling against the contextId returned synchronously in the charge request. See below example of context ID polling when passing L2 data.

query ID($inStoreContextId: ID!) {
	node(id: $inStoreContextId) {
		... on InStoreContext {
			id
			status
			reader {
				id
				name
				status
			}
			transaction {
				id
				legacyId
				orderId
				status
                purchaseOrderNumber
                tax {
                    taxAmount
                    taxExempt
                }
				statusHistory {
					__typename
					... on PaymentStatusEvent {
						status
						timestamp
						terminal
						__typename
						... on AuthorizedEvent {
							processorResponse {
								authorizationId
								emvData
								message
								legacyCode
								retrievalReferenceNumber
							}
						}
						__typename
						... on GatewayRejectedEvent {
							gatewayRejectionReason
						}
						__typename
						... on FailedEvent {
							processorResponse {
								retrievalReferenceNumber
								emvData
								message
								legacyCode
							}
							networkResponse {
								message
								code
							}
						}
						__typename
						... on ProcessorDeclinedEvent {
							processorResponse {
								legacyCode
								message
								authorizationId
								additionalInformation
								retrievalReferenceNumber
								emvData
							}
							declineType
							networkResponse {
								code
								message
							}
						}
					}
				}
				merchantAddress {
					company
					streetAddress
					addressLine1
					extendedAddress
					addressLine2
					locality
					adminArea2
					region
					adminArea1
					postalCode
					countryCode
					phoneNumber
				}
				amount {
					value
					currencyIsoCode
				}
				merchantAccountId
				merchantName
				createdAt

				channel
				customFields {
					name
					value
				}
				paymentMethodSnapshot {
					__typename
                    ...on PayPalTransactionDetails{
                          authorizationId
                        captureId
                        paymentId
                         appUsedForScanning
                         payer {
                             payerId
                             email
                             }
                        payer{
                            firstName
                            cobrandedCardLabel
                            billingAgreementId
                                }
                                sellerProtectionStatus
                            }

            ... on VenmoAccountDetails {
            username
            venmoUserId
          }

					... on CreditCardDetails {
						origin {
							type
							details {
								__typename
								... on CardPresentOriginDetails {
									authorizationMode
									inputMode
									pinVerified
									terminalId
								}
								... on EmvCardOriginDetails {
									authorizationMode
									inputMode
									pinVerified
									terminalId
									applicationPreferredName
									applicationIdentifier
									terminalVerificationResult
									cardSequenceNumber
									applicationInterchangeProfile
									terminalTransactionDate
									terminalTransactionType
									cashbackAmount
									applicationUsageControl
									terminalCountryCode
									applicationCryptogram
									cryptogramInformationData
									cardholderVerificationMethodResults
									applicationTransactionCounter
									unpredictableNumber
									issuerActionCodeDefault
									issuerActionCodeDenial
									issuerActionCodeOnline
								}
							}
						}
						brandCode
						last4
						bin
						expirationMonth
						expirationYear
						cardholderName
                        uniqueNumberIdentifier
						binData {
							issuingBank
							countryOfIssuance
							prepaid
							healthcare
							debit
							commercial
						}
					}
				}
			}
		}
	}
}

Level 3 Data Processing

Level 3 data is primarily transaction line item information as well as discount and shipping information which can be passed to Braintree using the following input fields: shipping (with additional TransactionShippingInput), discountAmount, and lineItems (with additional TransactionLineItemInput) as seen in the below example of a card present charge request:

mutation RequestChargeFromInStoreReader($input: RequestChargeFromInStoreReaderInput!) {
    requestChargeFromInStoreReader(input: $input) {
        clientMutationId
        id
        status
        reader {
            id
            name                
            status
        }
    }
}

Once the transaction is completed on the reader you will need to perform your POS polling against the contextId returned synchronously in the charge request. See below example of context ID polling when passing L3 data.

query ID($inStoreContextId: ID!) {
	node(id: $inStoreContextId) {
		... on InStoreContext {
			id
			status
			reader {
				id
				name
				status
			}
			transaction {
				id
				legacyId
				orderId
				status
                purchaseOrderNumber
                tax {
                    taxAmount
                    taxExempt
                }
                discountAmount
                shipping {
                    shippingAmount
                    shipsFromPostalCode
                    shippingAddress {
                    company
                    streetAddress
                    addressLine1
                    extendedAddress
                    addressLine2
                    firstName
                    lastName
                    locality
                    adminArea2
                    region
                    adminArea1
                    postalCode
                    countryCode
                    }
                }
				statusHistory {
					__typename
					... on PaymentStatusEvent {
						status
						timestamp
						terminal
						__typename
						... on AuthorizedEvent {
							processorResponse {
								authorizationId
								emvData
								message
								legacyCode
								retrievalReferenceNumber
							}
						}
						__typename
						... on GatewayRejectedEvent {
							gatewayRejectionReason
						}
						__typename
						... on FailedEvent {
							processorResponse {
								retrievalReferenceNumber
								emvData
								message
								legacyCode
							}
							networkResponse {
								message
								code
							}
						}
						__typename
						... on ProcessorDeclinedEvent {
							processorResponse {
								legacyCode
								message
								authorizationId
								additionalInformation
								retrievalReferenceNumber
								emvData
							}
							declineType
							networkResponse {
								code
								message
							}
						}
					}
				}
				merchantAddress {
					company
					streetAddress
					addressLine1
					extendedAddress
					addressLine2
					locality
					adminArea2
					region
					adminArea1
					postalCode
					countryCode
					phoneNumber
				}
				amount {
					value
					currencyIsoCode
				}
				merchantAccountId
				merchantName
				createdAt

				channel
				customFields {
					name
					value
				}
				paymentMethodSnapshot {
					__typename
                    ...on PayPalTransactionDetails{
                          authorizationId
                        captureId
                        paymentId
                         appUsedForScanning
                         payer {
                             payerId
                             email
                             }
                        payer{
                            firstName
                            cobrandedCardLabel
                            billingAgreementId
                                }
                                sellerProtectionStatus
                            }

            ... on VenmoAccountDetails {
            username
            venmoUserId
          }

					... on CreditCardDetails {
						origin {
							type
							details {
								__typename
								... on CardPresentOriginDetails {
									authorizationMode
									inputMode
									pinVerified
									terminalId
								}
								... on EmvCardOriginDetails {
									authorizationMode
									inputMode
									pinVerified
									terminalId
									applicationPreferredName
									applicationIdentifier
									terminalVerificationResult
									cardSequenceNumber
									applicationInterchangeProfile
									terminalTransactionDate
									terminalTransactionType
									cashbackAmount
									applicationUsageControl
									terminalCountryCode
									applicationCryptogram
									cryptogramInformationData
									cardholderVerificationMethodResults
									applicationTransactionCounter
									unpredictableNumber
									issuerActionCodeDefault
									issuerActionCodeDenial
									issuerActionCodeOnline
								}
							}
						}
						brandCode
						last4
						bin
						expirationMonth
						expirationYear
						cardholderName
                        uniqueNumberIdentifier
						binData {
							issuingBank
							countryOfIssuance
							prepaid
							healthcare
							debit
							commercial
						}
					}
				}
			}
		}
	}
}

Important Tips for passing L2/L3 data

  • When data is passed in the incorrect format, the reader will initially accept the API request and prompt for card insert; however, an error will be thrown once the card is tapped, and the transaction will not be processed. The final context status would be "FAILED".

  • The passing of L2/L3 data is NOT supported for offline transactions, and if these API fields are passed for an offline transaction, it will result in an API error.

  • We do not support the passing of L2/L3 data when using the Request Authorize API mutation; however, you may pass this data when you send the separate capture request.

Last updated