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.
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:
- GraphQL Mutation
- GraphQL Variables
- Sample API Response
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.
- GraphQL Query
- GraphQL Variables
- Sample API Response
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:
- GraphQL Mutation
- GraphQL Variables
- Sample API Response
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.
- GraphQL Mutation
- GraphQL Variables
- Sample API Response
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.
-
Make sure you are passing the L2/L3 data in the proper format according to the GraphQL API documentation.