# Merchant Purchase

The Merchant Purchase resource can be used to charge customers with credit or debit cards.

If a card hasn't been used before, a Merchant Session Purchase must be created and approved with that specific card before it can be used directly in a Merchant Purchase.

### The Merchant Purchase object

**Attributes**

| Name | Type | Description |
| --- | --- | --- |
| `id` | STRING | Unique id for the merchant purchase. |
| `amount` | INTEGER | Amount in cents to be received. Example: 100 (R$1.00). |
| `billingCity` | STRING | Billing city of the card used for the purchase. |
| `billingCountryCode` | STRING | Billing country code of the card used for the purchase. Example: "BRA". |
| `billingStateCode` | STRING | Billing state code of the card used for the purchase. Example: "SP". |
| `billingStreetLine1` | STRING | Billing street address of the card used for the purchase. |
| `billingStreetLine2` | STRING | Billing street address complement of the card used for the purchase. |
| `billingZipCode` | STRING | Billing zip code of the card used for the purchase. |
| `cardEnding` | STRING | Last 4 digits of the card. |
| `cardId` | STRING | ID of the Merchant Card used for the purchase. |
| `cardProductId` | STRING | First digits (BIN) of the card used for the purchase. |
| `challengeMode` | STRING | Holder verification mode. Options: "enabled", "disabled". |
| `challengeUrl` | STRING | URL where the card holder completes a verification requested by the issuer, when there is one. Empty for 3DS purchases (challengeMode "enabled"), which return a token for the Stark 3DS SDK instead. |
| `confirmationDeadline` | STRING | Datetime until which a purchase with confirmationMode "manual" can be confirmed. Confirmations are refused from 15 minutes before it, and purchases not confirmed by then are automatically canceled. The confirmation window is set with your account manager, from 1 to 28 days (default: 28 days). Example: "2020-05-21T23:00:00.000000+00:00". |
| `confirmationMode` | STRING | Purchase confirmation mode. Options: "automatic", "manual". |
| `created` | STRING | Creation datetime. Example: "2020-04-23T23:00:00.000000+00:00". |
| `currencyCode` | STRING | Currency code of the purchase. |
| `endToEndId` | STRING | End-to-end ID of the purchase. |
| `fee` | INTEGER | Fee charged in cents. |
| `fundingType` | STRING | Funding type. Options: "credit", "debit". |
| `holderEmail` | STRING | Email of the card holder. |
| `holderId` | STRING | Your identifier for the card holder. |
| `holderName` | STRING | Name of the card holder. |
| `holderPhone` | STRING | Phone number of the card holder. |
| `installmentCount` | INTEGER | Number of purchase installments. |
| `metadata` | OBJECT | Additional data sent on creation, such as the payer's device data of a 3DS purchase. |
| `network` | STRING | Card network. |
| `softDescriptor` | STRING | Text shown on the card holder's statement. |
| `source` | STRING | Source of the purchase. |
| `status` | STRING | Current purchase status. Options: "created", "pending", "processing", "approved", "denied", "confirmed", "paid", "canceled", "voided", "failed". |
| `tags` | LIST OF STRINGS | Tags associated with the purchase. |
| `transactionIds` | LIST OF STRINGS | Ledger transaction IDs linked to the purchase. |
| `updated` | STRING | Last update datetime. Example: "2020-04-23T23:00:00.000000+00:00". |

### Create Merchant Purchase

`POST /v2/merchant-purchase`

This route is used to charge a card that has been previously saved. Cards can only be used in this route once a previous purchase was approved through a Merchant Session Purchase.

Purchases with saved cards are credit only and cannot use 3DS: authentication runs in the card holder's browser and needs the full card number, which is never returned for a saved card. To authenticate a purchase, use a Merchant Session with challengeMode "enabled".

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `amount` | REQUIRED | A positive integer that represents the amount in cents to be received. Minimum: 100 (R$1.00). |
| `cardId` | REQUIRED | The ID of the Merchant Card to be used for the purchase. |
| `fundingType` | REQUIRED | The type of funding to be used for the purchase. Only "credit" is accepted for saved cards. |
| `challengeMode` | OPTIONAL | Only "disabled" is accepted for saved cards. Any other value returns the invalidChallengeMode error. Default: "disabled" |
| `confirmationMode` | OPTIONAL | Defines how the purchase is confirmed. With "automatic", an approved purchase is confirmed automatically. With "manual" (pre-authorization), the amount stays authorized on the card and the purchase remains approved until you confirm it with PATCH /v2/merchant-purchase/:id. Manual confirmation is only available for credit purchases and is not allowed for zero dollar purchases. Options are "automatic" and "manual". Default: "automatic" |
| `holderId` | OPTIONAL | Your identifier for the card holder, from 1 to 50 characters. It will soon become required, so we recommend sending it already. |
| `installmentCount` | OPTIONAL | A positive integer from 1 to 12 that represents the number of purchase installments. With more than one installment, each installment must be at least 500 (R$5.00). Default: 1 |
| `metadata` | OPTIONAL | An object containing additional data related to the purchase. |
| `softDescriptor` | OPTIONAL | Text shown on the card holder's statement, from 1 to 16 characters. |
| `tags` | OPTIONAL | Array of strings to tag the entity for future queries. All tags will be converted to lowercase. |

**Request**

```python
import starkbank

merchant_purchase = starkbank.merchantpurchase.create(
    starkbank.MerchantPurchase(
        amount=10000,
        installment_count=5,
        holder_email="tywin.lannister@gmail.com",
        holder_phone="11985923451",
        funding_type="credit",
        billing_country_code="BRA",
        billing_city="Sao Paulo",
        billing_state_code="SP",
        billing_street_line_1="Rua Casterly Rock, 2000",
        billing_street_line_2="1 andar",
        billing_zip_code="01450-000",
        metadata={
            "userAgent": "userAgent",
            "userIp": "184.82.170.183",
            "language": "pt-BR",
            "timezoneOffset": 3,
            "extraData": "extraData"
        },
        card_id="6295415968235520"
    )
)

print(merchant_purchase)
```

**Response**

```python
MerchantPurchase(
    amount=10000,
    billing_city=Sao Paulo,
    billing_country_code=BRA,
    billing_state_code=SP,
    billing_street_line_1=Rua Casterly Rock, 2000,
    billing_street_line_2=1 andar,
    billing_zip_code=01450-000,
    card_ending=0007,
    card_id=6295415968235520,
    challenge_mode=enabled,
    challenge_url=https://sandbox.api.starkinfra.com/v2/acquiring-purchase/5700835795271680/challenge,
    created=2025-02-20 20:47:43.237974,
    currency_code=BRL,
    end_to_end_id=1087c2ba-6a07-4108-82f7-14156032af48,
    fee=0,
    funding_type=credit,
    holder_email=tywin.lannister@gmail.com,
    holder_name=Tywin Lannister,
    holder_phone=11985923451,
    id=5136275203948544,
    installment_count=5,
    metadata={
        'extraData': 'extraData',
        'language': 'pt-BR',
        'screenHeight': 500
        'screenWidth': 500,
        'timezoneOffset': 3,
        'userAgent': 'userAgent',
        'userIp': '184.82.170.183'
    },
    network=mastercard,
    source=merchant-card/6295415968235520,
    status=pending,
    tags=[],
    updated=2025-02-20 20:47:45.176881
)
```

### Complete a 3DS Merchant Purchase

`POST /v2/merchant-purchase/:id/challenge`

Submit the result of the 3DS authentication to conclude the authorization of a purchase created through a Merchant Session with challengeMode "enabled". The purchase must have status "pending".

Your front-end obtains the challenge object from the Stark 3DS SDK and sends it to your backend, which calls this route. Send the object exactly as the SDK returned it: never remove fields or fill in xid or referenceId when they are null, because that invalidates the authentication.

The purchase status is returned as "approved" when the authorization succeeds, "denied" when it is declined, or "processing" when the authorization is still being concluded, in which case the final status is delivered by the merchant-purchase webhook.

Only call this route when the authentication succeeded. A pending purchase that is not completed within one hour fails and must be created again.

This route is currently not available in the SDKs.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `id` | REQUIRED | Id of the purchase entity. |
| `cavv` | REQUIRED | Cryptographic proof of the authentication, returned by the Stark 3DS SDK. |
| `eci` | REQUIRED | Electronic Commerce Indicator returned by the Stark 3DS SDK. Its meaning depends on the card network. |
| `version` | REQUIRED | 3DS protocol version returned by the Stark 3DS SDK. E.g.: "2.2.0". |
| `xid` | OPTIONAL | Authentication transaction identifier returned by the Stark 3DS SDK. Send it as returned, even when null. |
| `referenceId` | OPTIONAL | Authentication session reference returned by the Stark 3DS SDK. Send it as returned, even when null. |

### Refresh a 3DS Merchant Purchase token

`POST /v2/merchant-purchase/:id/challenge-token`

Issue a new 3DS token for a purchase with status "pending", in case the token returned on creation expired before the card holder finished the authentication. No request body is required.

The new token does not extend the purchase deadline: a pending purchase that is not completed within one hour of its creation fails.

This route is currently not available in the SDKs.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `id` | REQUIRED | Id of the purchase entity. |

### Update a Merchant Purchase

`PATCH /v2/merchant-purchase/:id`

Update a single purchase. The status sent defines the operation:

**confirmed**: confirms an approved purchase created with confirmationMode "manual" (pre-authorization). The amount can be the full authorized amount or a lower one, with a minimum of 100 (R$1.00). Only one confirmation can be in progress at a time, and confirmations are refused from 15 minutes before the purchase's confirmationDeadline. If the confirmation cannot be concluded right away, the response message is "Merchant Purchase confirmation in progress" and the purchase stays approved with a confirming log until it changes to confirmed. If the confirmation fails, a failed log is created and the purchase status does not change. After multiple failed attempts, the purchase is automatically canceled and can no longer be confirmed.
**canceled**: cancels the authorization of an approved purchase. The amount must be 0. The purchase stays approved while the cancellation is processed and then changes to canceled.
**reversed**: reverses a confirmed or paid purchase. The amount is the new amount of the purchase after the reversal. Send 0 for a full reversal, which changes the status to voided. For a partial reversal, the amount must be between 100 and the current amount minus 1, the status remains the same, and it is not allowed on the same day (GMT-3) as the purchase confirmation.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `id` | REQUIRED | Id of the purchase entity. |
| `amount` | REQUIRED | New amount of the purchase in cents. Example: 200 (R$2.00). |
| `status` | REQUIRED | Operation to be performed. Options: "confirmed", "canceled", "reversed". |

**Request**

```python
import starkbank

merchant_purchase = starkbank.merchantpurchase.update(id="5752391039188992", status="canceled", amount=0)

print(merchant_purchase)
```

**Response**

```python
MerchantPurchase(
    amount=0,
    billing_city=,
    billing_country_code=,
    billing_state_code=,
    billing_street_line_1=,
    billing_street_line_2=,
    billing_zip_code=,
    cardId="6675871284854784",
    card_ending="0005",
    challenge_mode="disabled",
    challenge_url="",
    created="2025-01-30T18:52:55.315590+00:00",
    currency_code="BRL",
    end_to_end_id="33c022ec-2c54-46e5-b20b-eb10edfaf021",
    fee=160,
    funding_type="credit",
    holder_email=,
    holder_name=Margaery Tyrell,
    holder_phone=,
    id="5752391039188992",
    installment_count=3,
    metadata={},
    network="visa",
    source="merchant-card/6675871284854784",
    status="confirmed",
    tags=["purchase_1234"],
    updated="2025-01-30T20:44:06.470183+00:00"
)
```

### Delete a Merchant Purchase

`DELETE /v2/merchant-purchase/:id`

Cancel or fully reverse a purchase. No request body is required.

If the purchase is approved, its authorization is canceled: the purchase stays approved while the cancellation is processed and then changes to canceled. If the purchase is confirmed or paid, it is fully reversed and its status changes to voided.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `id` | REQUIRED | Id of the purchase entity. |

### List Merchant Purchases

`GET /v2/merchant-purchase`

Get a list of merchant purchases in chunks of at most 100. If you need smaller chunks, use the limit parameter.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `after` | OPTIONAL | Filter entities created after this date. |
| `before` | OPTIONAL | Filter entities created before this date. |
| `cursor` | OPTIONAL | String used to get the next batch of results. Our SDKs handle this for you. |
| `fields` | OPTIONAL | List of strings to filter response JSON keys. Not available in the SDKs. |
| `holderId` | OPTIONAL | Filter purchases by the holderId informed on creation. |
| `ids` | OPTIONAL | List of strings to get specific entities by ids. |
| `limit` | OPTIONAL | Number of results per cursor. Max = 100. |
| `status` | OPTIONAL | Filter purchases by the specified status, such as: created, pending, processing, approved, denied, confirmed, paid, canceled, voided, failed. |
| `tags` | OPTIONAL | Filter entities that contain the specified tags. |

**Request**

```python
import starkbank

merchantpurchases = starkbank.merchantpurchase.query(limit=1, tags=["order/123"], status="approved")

for merchantpurchase in merchantpurchases:
    print(merchantpurchase)
```

**Response**

```python
MerchantPurchase(
    amount=10000,
    billing_city=Sao Paulo,
    billing_country_code=BRA,
    billing_state_code=SP,
    billing_street_line_1=Rua Casterly Rock, 2000,
    billing_street_line_2=1 andar,
    billing_zip_code=01450-000,
    card_ending=0007,
    id=6295415968235520,
    challenge_mode=enabled,
    challenge_url=,
    created=2025-02-20 20:47:43.237974,
    currency_code=BRL,
    end_to_end_id=1087c2ba-6a07-4108-82f7-14156032af48,
    fee=0,
    funding_type=credit,
    holder_email=tywin.lannister@gmail.com,
    holder_name=Margaery Tyrell,
    holder_phone=11985923451,
    id=5136275203948544,
    installment_count=5,
    metadata={
        'extraData': 'extraData',
        'language': 'pt-BR',
        'screenHeight': 500,
        'screenWidth': 500,
        'timezoneOffset': 3,
        'userAgent': 'userAgent',
        'userIp': '184.82.170.183'
    },
    network=mastercard,
    source=merchant-card/6295415968235520,
    status=pending,
    tags=[],
    updated=2025-02-20 20:47:46.491252
)
```

### Get a Merchant Purchase

`GET /v2/merchant-purchase/:id`

Retrieve detailed information about a specific purchase by its id.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `id` | REQUIRED | The unique identifier for the merchant purchase that needs to be retrieved. |
| `fields` | OPTIONAL | List of strings to filter response JSON keys. Not available in the SDKs. |

**Request**

```python
import starkbank

merchant_purchase = starkbank.merchantpurchase.get('5136275203948544')

print(merchant_purchase)
```

**Response**

```python
MerchantPurchase(
    amount=10000,
    billing_city=Sao Paulo,
    billing_country_code=BRA,
    billing_state_code=SP,
    billing_street_line_1=Rua Casterly Rock, 2000,
    billing_street_line_2=1 andar,
    billing_zip_code=01450-000,
    card_ending=0007,
    card_id=6295415968235520,
    challenge_mode=enabled,
    challenge_url=,
    created=2025-02-20 20:47:43.237974,
    currency_code=BRL,
    end_to_end_id=1087c2ba-6a07-4108-82f7-14156032af48,
    fee=0,
    funding_type=credit,
    holder_email=tywin.lannister@gmail.com,
    holder_name=Margaery Tyrell,
    holder_phone=11985923451,
    id=5136275203948544,
    installment_count=5,
    metadata={
        'extraData': 'extraData',
        'language': 'pt-BR',
        'screenHeight': 500,
        'screenWidth': 500,
        'timezoneOffset': 3,
        'userAgent': 'userAgent',
        'userIp': '184.82.170.183'
    },
    network=mastercard,
    source=merchant-card/6295415968235520,
    status=pending,
    tags=[],
    updated=2025-02-20 20:47:46.491252
)
```

### List Merchant Purchase Logs

`GET /v2/merchant-purchase/log`

Get a paged list of merchant purchase logs.

A log tracks a change in the purchase entity according to its life cycle.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `after` | OPTIONAL | Filter entities created after this date. |
| `before` | OPTIONAL | Filter entities created before this date. |
| `cursor` | OPTIONAL | String used to get the next batch of results. Our SDKs handle this for you. |
| `fields` | OPTIONAL | List of strings to filter response JSON keys. Not available in the SDKs. |
| `limit` | OPTIONAL | Number of results per cursor. Max = 100. |
| `purchaseIds` | OPTIONAL | Filter the merchant purchase ids to only include its corresponding logs |
| `types` | OPTIONAL | Filters logs by log types. |

**Request**

```python
import starkbank

merchant_purchase_logs = starkbank.merchantpurchase.log.query(limit=1)

for log in merchant_purchase_logs:
    print(log)
```

**Response**

```python
Log(    
    created=2025-02-20 20:51:47.554421,
    errors=[],
    id=4529865642475520,
    purchase=MerchantPurchase(
        amount=180,
        billing_city=São Paulo,
        billing_country_code=BRA,
        billing_state_code=SP,
        billing_street_line_1=Rua do Holder Name, 123,
        billing_street_line_2=,
        billing_zip_code=11111-111,
        card_ending=9733,
        card_expiration=None,
        card_id=,
        card_number=None,
        card_security_code=None,
        challenge_mode=disabled,
        challenge_url=,
        created=2024-07-16 19:42:25.059361,
        currency_code=BRL,
        end_to_end_id=ee77111c-644c-4a67-a4cf-6cbc9da15ceb,
        fee=0,
        funding_type=credit,
        holder_email=holdeName@email.com,
        holder_name=Holder Name,
        holder_phone=11111111111,
        id=4512566093021184,
        installment_count=12,
        metadata={},
        network=mastercard,
        source=merchant-session/5375106121465856,
        status=created,
        tags=['yourtags'],
        updated=2024-07-16 19:42:26.878894
    ),
    type=canceling
)
```

### Get a Merchant Purchase Log

`GET /v2/merchant-purchase/log/:id`

Get a single merchant purchase log by its id.

**Parameters**

| Name | Required | Description |
| --- | --- | --- |
| `id` | REQUIRED | The unique identifier for the merchant purchase that needs to be retrieved. |
| `fields` | OPTIONAL | List of strings to filter response JSON keys. Not available in the SDKs. |

**Request**

```python
import starkbank

log = starkbank.merchantpurchase.log.get('4529865642475520')

print(log)
```

**Response**

```python
Log(
    created=2025-02-20 20:51:47.554421,
    errors=[],
    id=4529865642475520,
    purchase=MerchantPurchase(
        amount=180,
        billing_city=São Paulo,
        billing_country_code=BRA,
        billing_state_code=SP,
        billing_street_line_1=Rua do Holder Name, 123,
        billing_street_line_2=,
        billing_zip_code=11111-111,
        card_ending=9733,
        card_id=,
        challenge_mode=disabled,
        challenge_url=,
        created=2024-07-16 19:42:25.059361,
        currency_code=BRL,
        end_to_end_id=ee77111c-644c-4a67-a4cf-6cbc9da15ceb,
        fee=0,
        funding_type=credit,
        holder_email=holdeName@email.com,
        holder_name=Holder Name,
        holder_phone=11111111111,
        id=4512566093021184,
        installment_count=12,
        metadata={},
        network=mastercard,
        source=merchant-session/5375106121465856,
        status=created,
        tags=['yourtags'],
        updated=2024-07-16 19:42:26.878894
    ),
    type=canceling
)
```

## Available Languages

Code samples on this page are in Python. The same content is available with samples in:

- [Python](https://docs.starkbank.com/api/v2/merchant-purchase-python.md)
- [Node.js](https://docs.starkbank.com/api/v2/merchant-purchase-node.md)
- [PHP](https://docs.starkbank.com/api/v2/merchant-purchase-php.md)
- [Java](https://docs.starkbank.com/api/v2/merchant-purchase-java.md)
- [Ruby](https://docs.starkbank.com/api/v2/merchant-purchase-ruby.md)
- [Elixir](https://docs.starkbank.com/api/v2/merchant-purchase-elixir.md)
- [.NET](https://docs.starkbank.com/api/v2/merchant-purchase-dotnet.md)
- [Go](https://docs.starkbank.com/api/v2/merchant-purchase-go.md)
- [Clojure](https://docs.starkbank.com/api/v2/merchant-purchase-clojure.md)
- [cURL](https://docs.starkbank.com/api/v2/merchant-purchase-curl.md)
