> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trymaven.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authorize.net Setup

> Connect your Authorize.net account to Maven

# Connecting Authorize.net

Maven connects to Authorize.net using your API Login ID and Transaction Key. These credentials allow Maven to create charges and customer profiles on your behalf.

## Prerequisites

* An Authorize.net merchant account
* API Login ID and Transaction Key from your Authorize.net account
* A Maven app

## Getting Your Credentials

<Steps>
  <Step title="Log in to Authorize.net">
    Go to [Authorize.net Merchant Interface](https://account.authorize.net/) and log in.
  </Step>

  <Step title="Navigate to API Credentials">
    Go to **Account > Settings > API Credentials & Keys**.
  </Step>

  <Step title="Copy API Login ID">
    Your **API Login ID** is displayed at the top of the page. Copy it.
  </Step>

  <Step title="Generate Transaction Key">
    Under **Create New Key(s)**, select **New Transaction Key** and click **Submit**. Copy the generated key — it won't be shown again.
  </Step>
</Steps>

## Connecting in Maven

<Steps>
  <Step title="Go to Payments">
    In the [Maven Dashboard](https://app.trymaven.com), navigate to your app and click the **Payments** tab.
  </Step>

  <Step title="Click Connect Authorize.net">
    Click the Authorize.net card and enter your credentials.
  </Step>

  <Step title="Enter Credentials">
    * **API Login ID**: Your Authorize.net API Login ID
    * **Transaction Key**: Your Authorize.net Transaction Key
  </Step>

  <Step title="Save">
    Click **Connect**. Maven will validate the credentials and save them.
  </Step>
</Steps>

## Sandbox Testing

For testing, use [Authorize.net Sandbox](https://sandbox.authorize.net/) credentials. Create a sandbox account at [developer.authorize.net](https://developer.authorize.net/).

Use sandbox credentials with `mvn_test_` API keys to test without real charges. Sandbox responses include real `transaction_id`, `auth_code`, AVS, CVV, CAVV, and network transaction ID values, so the payload your code receives in test mode matches what you'll see in production.

## Capture Mode

Maven supports two capture modes for Authorize.net charges. The setting is per-app and can be changed any time from the **Payments** tab on the Authorize.net card.

| Mode                       | Behavior                                                                                                                                                                                                                                                         |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Auto Capture** (default) | Maven sends `authCaptureTransaction`. Funds are authorized and captured immediately. This is the standard flow.                                                                                                                                                  |
| **Authorize Only**         | Maven sends `authOnlyTransaction`. Funds are placed on hold but **not** captured. You settle the charge later from your Authorize.net dashboard or via your own `priorAuthCaptureTransaction` API call, using the `transaction_id` Maven returns in the webhook. |

**When to use Authorize Only:**

* Hotels, car rentals, and other businesses that authorize on booking and capture on checkout
* Service businesses where the final amount may change before fulfillment
* Any flow where you want to verify the card and reserve funds without immediately moving money

**Important notes:**

* Authorizations typically expire **30 days** after creation if not captured. Holds beyond that are released.
* Once captured, the captured amount is locked and cannot be increased.
* You can capture for **less than** the original auth amount (partial capture).
* Maven does not currently send a follow-up webhook when you capture in Authorize.net — you track captures on your side.

When Authorize Only is enabled, the session reaches the new terminal status `payment-authorized` instead of `payment-success`, and the webhook payload includes `processor.auth_only: true`.

## Processor Response Fields

### Charge Mode

| Field              | Description                                                                                          |
| ------------------ | ---------------------------------------------------------------------------------------------------- |
| `transaction_id`   | Authorize.net transaction ID. In Authorize Only mode, use this as the `refTransId` to capture later. |
| `auth_code`        | Authorization code from the issuing bank                                                             |
| `response_code`    | Authorize.net response code (`1`=Approved, `2`=Declined, `3`=Error, `4`=Held for review)             |
| `avs_result_code`  | AVS (Address Verification System) match result                                                       |
| `cvv_result_code`  | CVV match result                                                                                     |
| `cavv_result_code` | CAVV (3D Secure) result                                                                              |
| `network_trans_id` | Card network transaction ID (Visa/Mastercard) — used for card-on-file flows and certain refunds      |
| `auth_only`        | `true` when the charge was made in Authorize Only mode (auth without capture)                        |
| `card_brand`       | Card brand                                                                                           |
| `card_last4`       | Last 4 digits                                                                                        |

### Result Code Cheat Sheet

**`response_code`** — overall transaction outcome:

| Code | Meaning                      |
| ---- | ---------------------------- |
| `1`  | Approved                     |
| `2`  | Declined                     |
| `3`  | Error                        |
| `4`  | Held for review (FDS filter) |

**`avs_result_code`** — billing address verification:

| Code | Meaning                             |
| ---- | ----------------------------------- |
| `Y`  | Address and zip both matched (best) |
| `A`  | Address matched, zip didn't         |
| `Z`  | Zip matched, address didn't         |
| `N`  | Neither matched                     |
| `U`  | AVS unavailable                     |
| `P`  | Not applicable for this card type   |

### Improving AVS Coverage

By default, voice sessions only collect the ZIP code from the caller — so AVS returns `Z` (zip match only) or `U` (unavailable) when no ZIP was captured. Strict Authnet AVS reject filters often decline both, which can block legitimate transactions.

To get a full AVS match (`Y`), pass a `billing_address` block on session creation. We forward it to Authnet's `billTo` on both charge and tokenize paths:

```bash theme={"dark"}
POST /v1/sessions
Authorization: Bearer mvn_live_xxx
Content-Type: application/json

{
  "project": "my-store",
  "caller": "+14155551234",
  "amount": "49.99",
  "mode": "charge",
  "gateway": "authorizenet",
  "billing_address": {
    "street": "123 Main St",
    "city":   "Austin",
    "state":  "TX",
    "zip":    "78701",
    "country": "US"
  }
}
```

<Note>
  Always pass the cardholder's **billing** address — the one on file with the card issuer — not the shipping address. AVS only matches against billing. If you reuse a shipping address that differs from billing, AVS will return `N` (no match), which most fraud filters reject.
</Note>

`first_name` and `last_name` on the `billing_address` are optional — when omitted, we fall back to the cardholder name collected during card capture. See the [API reference for `POST /v1/sessions`](/api-reference/POST/v1/sessions) for the full field list and validation rules.

#### Tokenize mode (CIM)

When you pass `billing_address` with `mode: "tokenize"`, the address is stored on the resulting CIM Payment Profile. Subsequent charges against that profile (via `createTransactionFromProfile`) inherit the billing address automatically — no need to re-send it on the charge call, unless you explicitly override `billTo` in your charge request.

**`cvv_result_code`** — CVV match:

| Code | Meaning                                    |
| ---- | ------------------------------------------ |
| `M`  | Match                                      |
| `N`  | No match                                   |
| `P`  | Not processed                              |
| `S`  | Should be on the card but wasn't submitted |
| `U`  | Issuer doesn't support CVV verification    |

**`cavv_result_code`** — 3D Secure / cardholder authentication:

| Code    | Meaning                              |
| ------- | ------------------------------------ |
| (blank) | CAVV not validated                   |
| `0`     | Not validated, possibly not supplied |
| `1`     | Failed validation                    |
| `2`     | Passed validation                    |
| `3`/`4` | Could not be performed               |

### Tokenize Mode (CIM)

| Field                         | Description             |
| ----------------------------- | ----------------------- |
| `authnet_customer_profile_id` | CIM Customer Profile ID |
| `authnet_payment_profile_id`  | CIM Payment Profile ID  |
| `card_brand`                  | Card brand              |
| `card_last4`                  | Last 4 digits           |

## Using Tokenized Cards

After tokenizing, use the CIM profile IDs to create transactions via the Authorize.net API:

```python theme={"dark"}
# Create a charge using CIM profile
from authorizenet import apicontractsv1 as api

transaction = api.createTransactionRequest()
transaction.transactionRequest.transactionType = "authCaptureTransaction"
transaction.transactionRequest.amount = "49.99"
transaction.transactionRequest.profile = api.customerProfilePaymentType()
transaction.transactionRequest.profile.customerProfileId = "123456789"  # from authnet_customer_profile_id
transaction.transactionRequest.profile.paymentProfile = api.paymentProfile()
transaction.transactionRequest.profile.paymentProfile.paymentProfileId = "987654321"  # from authnet_payment_profile_id
```
