# Quick Start Guide

Process your first payment in 5 minutes with AuxCORE on **Sandbox**.

---

## What you'll build

- Authenticate with your API key
- Test the connection
- Process a test sale
- Look up the transaction
- Issue a refund

**Time:** ~5 minutes  
**Level:** Beginner

---

## Prerequisites

- A **Sandbox** dashboard login at `https://uat.auxcore.net`
- A **Secret API key** (`api-…`) — Dashboard → **Settings → Developer & Integrations → API Keys**. Not the SDK public key (`lpk_live_…`): that one only works in the browser.
- `curl` or any HTTP client

The key alone identifies your tenant and merchant, so no tenant or merchant ID is needed.

---

## Base URL

Pick the host that matches your dashboard login:

| Environment | `BASE_URL` |
|-------------|------------|
| Sandbox | `https://uat.auxcore.net/api/v1/public` |
| Production | `https://app.auxcore.net/api/v1/public` |

This guide uses **Sandbox**. Replace the host if you are on production.

---

## Step 1: Environment variables

Export your key once. Every snippet below reads it from the environment, whichever language you pick.

```bash
export API_KEY="YOUR_SECRET_API_KEY"
export BASE_URL="https://uat.auxcore.net/api/v1/public"
```

The Node.js, Python and PHP snippets share this small helper. Paste it at the top of your script:

<!-- tabs -->

```javascript
// quickstart.mjs — Node.js 18+ (built-in fetch)
const BASE_URL = process.env.BASE_URL ?? 'https://uat.auxcore.net/api/v1/public';

async function auxcore(method, path, body) {
  const res = await fetch(`${BASE_URL}${path}`, {
    method,
    headers: { 'x-api-key': process.env.API_KEY, 'Content-Type': 'application/json' },
    body: body ? JSON.stringify(body) : undefined,
  });
  return { status: res.status, body: await res.json() };
}
```

```python
# quickstart.py — Python 3.8+, pip install requests
import os
import requests

BASE_URL = os.environ.get("BASE_URL", "https://uat.auxcore.net/api/v1/public")
session = requests.Session()
session.headers.update({"x-api-key": os.environ["API_KEY"]})
```

```php
<?php
// quickstart.php — PHP 7.4+ with the curl extension
define('BASE_URL', getenv('BASE_URL') ?: 'https://uat.auxcore.net/api/v1/public');

function auxcore(string $method, string $path, ?array $body = null): array
{
    $ch = curl_init(BASE_URL . $path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('API_KEY'), 'Content-Type: application/json'],
    ]);
    if ($method !== 'GET') {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body ?? new stdClass()));
    }
    $response = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    return [$status, $response];
}
```

<!-- /tabs -->

---

## Step 2: Test connection

<!-- tabs -->

```bash
curl -X POST "$BASE_URL/testConnection" \
  -H "x-api-key: $API_KEY"
```

```javascript
const connection = await auxcore('POST', '/testConnection');
console.log(connection.status, connection.body.message);
```

```python
connection = session.post(f"{BASE_URL}/testConnection")
print(connection.status_code, connection.json()["message"])
```

```php
[$status, $connection] = auxcore('POST', '/testConnection');
echo $status, ' ', $connection['message'], PHP_EOL;
```

<!-- /tabs -->

Expect HTTP 200 with `"success": true` and a `message` naming the merchant the key belongs to.

---

## Step 3: Process a test sale

The Public API never accepts raw card numbers on Sandbox or Production. You first exchange the card for a `pciToken`, then charge the token.

### 3a. Tokenize a test card

On Sandbox, the quickest way to get a token is to send a [test card](./testing.md#test-cards) to `/tokenize-card` with your secret key:

<!-- tabs -->

```bash
curl -X POST "$BASE_URL/tokenize-card" \
  -H "x-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cardNumber": "4111111111111111",
    "expiryMonth": "12",
    "expiryYear": "2030",
    "cvv": "123",
    "cardHolderName": "Test Customer"
  }'

# Copy data.pciToken from the response
export PCI_TOKEN="pci_tok_8f2c1a9b7e4d"
```

```javascript
const tokenized = await auxcore('POST', '/tokenize-card', {
  cardNumber: '4111111111111111',
  expiryMonth: '12',
  expiryYear: '2030',
  cvv: '123',
  cardHolderName: 'Test Customer',
});
const pciToken = tokenized.body.data.pciToken;
```

```python
tokenized = session.post(f"{BASE_URL}/tokenize-card", json={
    "cardNumber": "4111111111111111",
    "expiryMonth": "12",
    "expiryYear": "2030",
    "cvv": "123",
    "cardHolderName": "Test Customer",
})
pci_token = tokenized.json()["data"]["pciToken"]
```

```php
[$status, $tokenized] = auxcore('POST', '/tokenize-card', [
    'cardNumber' => '4111111111111111',
    'expiryMonth' => '12',
    'expiryYear' => '2030',
    'cvv' => '123',
    'cardHolderName' => 'Test Customer',
]);
$pciToken = $tokenized['data']['pciToken'];
```

<!-- /tabs -->

```json
{
  "success": true,
  "data": {
    "pciToken": "pci_tok_8f2c1a9b7e4d",
    "last4": "1111",
    "cardBrand": "visa",
    "singleUse": true,
    "status": "active"
  }
}
```

Tokenize the card again for each new sale. To charge the same card later, save it on file with `saveCard` (see [Transactions](../core/transactions.md)).

> **Production:** sending card numbers from your server puts that server in PCI scope. For real customers, collect the card in the browser with the [PCI SDK](./sdks.md), which tokenizes inside a hosted iframe and hands your page only the `pciToken`.

### 3b. Charge the token

<!-- tabs -->

```bash
curl -X POST "$BASE_URL/transaction" \
  -H "x-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "Amount": 10.00,
    "SuggestedMode": "Card",
    "pciToken": "'"$PCI_TOKEN"'",
    "BillingCustomerName": "Test Customer",
    "BillingEmail": "test@example.com",
    "BillingPostalCode": "78701"
  }'

# Copy data.TransactionId from the response
export TRANSACTION_ID="550e8400-e29b-41d4-a716-446655440020"
```

```javascript
const sale = await auxcore('POST', '/transaction', {
  Amount: 10.0,
  SuggestedMode: 'Card',
  pciToken,
  BillingCustomerName: 'Test Customer',
  BillingEmail: 'test@example.com',
  BillingPostalCode: '78701',
});
const transactionId = sale.body.data.TransactionId;
console.log(sale.status, sale.body.data.Status); // 200 "1" = approved
```

```python
sale = session.post(f"{BASE_URL}/transaction", json={
    "Amount": 10.00,
    "SuggestedMode": "Card",
    "pciToken": pci_token,
    "BillingCustomerName": "Test Customer",
    "BillingEmail": "test@example.com",
    "BillingPostalCode": "78701",
})
transaction_id = sale.json()["data"]["TransactionId"]
print(sale.status_code, sale.json()["data"]["Status"])  # 200 "1" = approved
```

```php
[$status, $sale] = auxcore('POST', '/transaction', [
    'Amount' => 10.00,
    'SuggestedMode' => 'Card',
    'pciToken' => $pciToken,
    'BillingCustomerName' => 'Test Customer',
    'BillingEmail' => 'test@example.com',
    'BillingPostalCode' => '78701',
]);
$transactionId = $sale['data']['TransactionId'];
echo $status, ' ', $sale['data']['Status'], PHP_EOL; // 200 "1" = approved
```

<!-- /tabs -->

**Approved response (abbreviated):**
```json
{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Transaction approved",
  "data": {
    "TransactionId": "550e8400-e29b-41d4-a716-446655440020",
    "Status": "1",
    "Amount": 10.00,
    "BaseAmount": 10.00,
    "ConvenienceFee": 0,
    "AuthCode": "123456",
    "ResponseCode": "100",
    "ResponseMessage": "Approved"
  }
}
```

- `Status: "1"` = approved (`"2"` pending, `"9"` declined)  
- `ResponseCode: "100"` = approval (codes are normalized to the NMI convention)  
- A decline returns HTTP **402** with `"status": "declined"`  

---

## Step 4: Get transaction details

<!-- tabs -->

```bash
curl "$BASE_URL/transaction/$TRANSACTION_ID" \
  -H "x-api-key: $API_KEY"
```

```javascript
const lookup = await auxcore('GET', `/transaction/${transactionId}`);
console.log(lookup.body.data);
```

```python
lookup = session.get(f"{BASE_URL}/transaction/{transaction_id}")
print(lookup.json()["data"])
```

```php
[$status, $lookup] = auxcore('GET', '/transaction/' . $transactionId);
print_r($lookup['data']);
```

<!-- /tabs -->

---

## Step 5: Refund

<!-- tabs -->

```bash
curl -X POST "$BASE_URL/refund" \
  -H "x-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transactionId": "'"$TRANSACTION_ID"'"
  }'
```

```javascript
const refund = await auxcore('POST', '/refund', { transactionId });
console.log(refund.status, refund.body.message);
```

```python
refund = session.post(f"{BASE_URL}/refund", json={"transactionId": transaction_id})
print(refund.status_code, refund.json()["message"])
```

```php
[$status, $refund] = auxcore('POST', '/refund', ['transactionId' => $transactionId]);
echo $status, ' ', $refund['message'], PHP_EOL;
```

<!-- /tabs -->

`transactionId` (also accepted as `TransactionId` or `transaction_id`) is the `data.TransactionId` from the sale. Add `amount` for a partial refund; omit it for a full refund.

---

## Test cards (Sandbox)

To try a decline or another card brand, repeat Step 3 with a different card from the [test card list](./testing.md#test-cards).

---

## Next steps

1. [SDK embed →](./sdks.md) — no-code checkout with `lpk_live_…` keys  
2. [Transactions →](../core/transactions.md)  
3. [Payment links →](../invoicing/invoices.md)  
4. [Webhooks →](./webhooks.md)  
5. [All endpoints →](../reference/endpoints.md)

---

## Troubleshooting

| Error | Fix |
|-------|-----|
| 401 `API key required` | Send the `x-api-key` header |
| 401 `API key validation failed` (or `Invalid API key`) | Key unknown, disabled or from the other environment — check `/settings/developer/api-keys` |
| 400 `PCI_SCOPE_VIOLATION` | Raw card data not allowed here — send a `pciToken` |
| 403 on `/tokenize-card` | You used the SDK public key — use the secret key |
| 402 declined (`Status: "9"`) | Tokenize an approved [test card](./testing.md#test-cards) on Sandbox |

---

**Questions?** Contact support@auxcore.net
