Creating Transactions

The GraphQL API currently supports two primary ways of creating transactions:

  1. The chargePaymentMethod mutation creates a transaction and captures funds immediately, beginning the process of actually transferring money from the customer to your bank account.
  2. The authorizePaymentMethod and captureTransaction mutations create a transaction and capture funds separately.
  3. The authorizePaymentMethod and partialCaptureTransaction mutations create a transaction and capture the funds in multiple partial amounts.

Which you choose depends on your requirements. In most cases, you’ll want to submit a transaction for settlement at the same time that you authorize the payment by using chargePaymentMethod.

However, there are some cases where you would want to create a transction but not yet capture funds—for example, if you ship physical goods. In this case, you could use authorizePaymentMethod at the time of the sale, which puts the money on hold against your customer's payment method, and then use captureTransaction once the item has shipped.

If you send physical goods to customers in multiple shipments, you can use authorizePaymentMethod at the time of sale to create a parent authorization for the entire amount. As each shipment ships, you can capture that partial amount in a child transaction using partialCaptureTransaction against the original authorization.

Charging a Payment Method

In order to charge a payment method with chargePaymentMethod, you'll need a payment method's ID, and information about the transaction you'd like to create using it.

If you charge a single-use payment method, this will consume it and you will no longer be able to look up, charge, or vault that payment method.

Mutation

mutation ExampleCharge($input: ChargePaymentMethodInput!) {
  chargePaymentMethod(input: $input) {
    transaction {
      id
      status
    }
  }
}

Variables

{
  "input": {
    "paymentMethodId": "id_of_payment_method",
    "transaction": {
      "amount": "11.23"
    }
  }
}

Full Request

To plug this mutation into a curl request, compose the query and variables into a JSON-valid string and send it in the request body. For example:

curl \
 -H 'Content-Type: application/json' \
 -H 'Authorization: Basic PUBLICKEY:PRIVATEKEY_BASE64ENCODED' \
 -H 'Braintree-Version: 2019-01-01' \
 -X POST https://payments.sandbox.braintree-api.com/graphql \
 -d '{
  "query": "mutation ExampleCharge($input: ChargePaymentMethodInput!) {
    chargePaymentMethod(input: $input) {
      transaction {
        id
        status
      }
    }
  }",
  "variables": {
    "input": {
      "paymentMethodId": "id_of_payment_method",
      "transaction": {
        "amount": "11.23"
      }
    }
  }
}'

There are many more possible fields you can use in the input or request in the output; see the API Explorer for more.

Response

A successful charge results in a transaction with the SUBMITTED_FOR_SETTLEMENT status:

{
  "data": {
    "transaction": {
      "id": "id_of_transaction",
      "status": "SUBMITTED_FOR_SETTLEMENT"
    }
  }
}

Using Separate Authorization and Capture

If you require a separate authorization step before charging the payment method to actually capture funds, the GraphQL API provides the authorizePaymentMethod and captureTransaction mutations.

Mutation

mutation ExampleAuth($input: AuthorizePaymentMethodInput!) {
  authorizePaymentMethod(input: $input) {
    transaction {
      id
      status
    }
  }
}

Variables

{
  "input": {
    "paymentMethodId": "id_of_payment_method",
    "transaction": {
      "amount": "11.23"
    }
  }
}

Response

A successful authorization results in a transaction with the AUTHORIZED status:

{
  "data": {
    "transaction": {
      "id": "id_of_authorized_transaction",
      "status": "AUTHORIZED"
    }
  }
}

Once you have authorized your payment method and are ready to capture funds, you should use the captureTransaction mutation. This mutation only requires the ID of the transaction that you'd like to capture.

You have a limited number of days to capture a transaction once it has been authorized.

Mutation

mutation ExampleCapture($input: CaptureTransactionInput!) {
  captureTransaction(input: $input) {
    transaction {
      id
      status
    }
  }
}

Variables

{
  "input": {
    "transactionId": "id_of_authorized_transaction"
  }
}

Response

A successful charge results in a transaction with the SUBMITTED_FOR_SETTLEMENT status:

{
  "data": {
    "transaction": {
      "id": "id_of_authorized_transaction",
      "status": "SUBMITTED_FOR_SETTLEMENT"
    }
  }
}

Using Multiple Partial Capture

To capture a transaction in multiple parts:

  1. Authorize the entire order amount with either of the authorizePaymentMethod or authorizePayPalAccount mutations.
  2. Make a separate call to the partialCaptureTransaction mutation for each amount you want to capture separately. In each call, specify the ID of the parent authorized transaction and the amount you wish to capture.

Once you have authorized the payment method as outlined in Using Separate Authorization and Capture, you can partially capture funds with the partialCaptureTransaction mutation. This mutation requires the amount you want to collect as well as the ID of the authorized transaction.

Mutation

mutation ExamplePartialCapture($input: partialCaptureTransactionInput!) {
  partialCaptureTransaction(input: $input) {
    transaction {
      id
      status
    }
  }
}

Variables

{
  "input": {
    "transactionId": "id_of_authorized_transaction",
    "amount": "5.45"
  }
}

Response

The mutation is successful if the resulting partial capture transaction is in the SETTLING, SUBMITTED_FOR_SETTLEMENT, or SETTLED state. The parent transaction will have a status of SETTLEMENT_PENDING.

{
  "data": {
    "capture": {
      "id": "id_of_child_transaction",
      "status": "SETTLING"
    }
  }
}

For more information about the lifecycle of partial capture transactions, see our full guide on multiple partial capture.

Transaction IDs

After charging a payment method, you may want to store the ID of the resulting transaction in your database for future reference, either for presenting back in the UI at a later time, or for your own internal book-keeping, analysis, or reporting requirements. You can retrieve this transaction by its ID using the node query.

Transaction Statuses

Even if the chargePaymentMethod or authorizePaymentMethod mutation doesn't return any errors, the transaction may not have been created successfully. For instance, the customer's card-issuing bank may have declined the authorization, or your fraud protection settings may have blocked it. In this case, the Transaction will have a failure status, such as Processor Declined or Gateway Rejected, and further information on what caused the failure. You can then use this to decide how to handle the failure and how to report it back to your customer.

A successful transaction will be updated over time as funds are debited from the customer and sent to you. As money moves, the transaction passes through multiple states in the payment lifecycle, most typically from Authorized to Submitted for Settlement, to Settling, to Settled. For detailed information on what these statuses mean, see the Transaction Lifecycle.

Using the complete list of transaction statuses and their meanings, you can check the status of a transaction to determine if it was successful or unsuccessful and why, and if successful, what will happen to the transaction next. This simplified status diagram shows what happens to a transaction if it succeeds or fails various validations.

Error Handling

Unsuccessful transactions are a normal part of transaction processing and should not be considered exceptional. If an error occurs, you will either not receive a transaction object on the payload, or you will receive only a partial object.

Here's an example of an error on a transaction.

{
  "data": {
    "chargePaymentMethod": null
  },
  "errors": [
    {
      "message": "Amount must be greater than zero.",
      "path": ["chargePaymentMethod"],
      "extensions": {
        "errorType": "user_error",
        "errorClass": "VALIDATION",
        "legacyCode": "81531",
        "inputPath": ["input", "transaction", "amount"]
      }
    }
  ],
  "extensions": {
    "requestId": "abc-123-def-456"
  }
}

See more details on handling errors in Making API Calls.

Testing

We provide test single-use payment methods in Sandbox, which can be used instead of tokenizing a new payment method every time. Pass any of these payment method "nonces" as the paymentMethodId in the chargePaymentMethod mutation. Or, to test vaulted payment methods, use one of these test single-use payment methods in a vaultPaymentMethod mutation, then pass the resulting payment method's ID into the chargePaymentMethod mutation.

To test processor responses, you can use these test values as the transaction amount.