# Pull API Tutorial
source: https://developer.mastercard.com/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/pull-api-tutorial/index.md

## Retrieve and Acknowledge Alerts with the Ethoca Alerts for Merchants Pull API {#retrieve-and-acknowledge-alerts-with-the-ethoca-alerts-for-merchants-pull-api}

This tutorial demonstrates how to retrieve alerts from Ethoca using the Pull API, acknowledge receipt, and prepare data for outcome submission.

*** ** * ** ***

## Overview {#overview}

The Pull API workflow consists of three steps:

1. **Retrieve Alerts** --- Call `GET /alerts` to fetch unacknowledged alerts
2. **Acknowledge Receipt** --- Call `POST /alerts/acknowledges` to confirm processing
3. **Submit Outcomes** --- Call `POST /outcomes` to report investigation results

This tutorial covers steps 1 and 2. See [Outcome API Tutorial](https://static.developer.mastercard.com/content/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/pull-api-tutorial/outcome-api-tutorial.md) for step 3.

*** ** * ** ***

## Step 1: Retrieve Alerts {#step-1-retrieve-alerts}

### Request {#request}

Retrieve a batch of alerts with optional filtering:

```bash
curl --request GET \
  --url 'https://sandbox.api.ethocaweb.com/ethoca/alerts/merchants/alerts?alert_type=CUSTOMERDISPUTE&size=10' \
  --header 'Authorization: OAuth oauth_consumer_key="YOUR_CONSUMER_KEY", oauth_signature_method="RSA-SHA256", oauth_signature="...", oauth_timestamp="...", oauth_nonce="..."' \
  --header 'Accept: application/json'
```

#### Query Parameters {#query-parameters}

|  Parameter   |  Type   | Required |                         Description                         |      Example      |
|--------------|---------|----------|-------------------------------------------------------------|-------------------|
| `alert_type` | String  | No       | Filter by alert type: `CUSTOMERDISPUTE` or `CONFIRMEDFRAUD` | `CUSTOMERDISPUTE` |
| `from_date`  | String  | No       | Start date (YYYY-MM-DD format)                              | `2024-06-01`      |
| `to_date`    | String  | No       | End date (YYYY-MM-DD format)                                | `2024-06-23`      |
| `size`       | Integer | No       | Number of results (1--1000)                                 | `10`              |

### Response {#response}

```json
{
  "alerts": [
    {
      "alertId": "ALERT_ID_001",
      "alertType": "CUSTOMERDISPUTE",
      "transactionAmount": "150.00",
      "transactionCurrency": "USD",
      "dateSubmitted": "2024-06-23",
      "customerName": "Jane Smith",
      "cardLastFour": "5678",
      "merchantName": "Example Merchant",
      "transactionRef": "TXN_REF_001",
      "transactionDate": "2024-06-20",
      "acquirerReference": "ACQ_REF_001"
    },
    {
      "alertId": "ALERT_ID_002",
      "alertType": "CONFIRMEDFRAUD",
      "transactionAmount": "250.00",
      "transactionCurrency": "USD",
      "dateSubmitted": "2024-06-23",
      "customerName": "John Doe",
      "cardLastFour": "1234",
      "merchantName": "Example Merchant",
      "transactionRef": "TXN_REF_002",
      "transactionDate": "2024-06-21",
      "acquirerReference": "ACQ_REF_002"
    }
  ]
}
```

#### Response Fields {#response-fields}

|         Field         |  Type  |                            Description                             |
|-----------------------|--------|--------------------------------------------------------------------|
| `alertId`             | String | Unique identifier for this alert (use for acknowledge and outcome) |
| `alertType`           | String | Either `CUSTOMERDISPUTE` or `CONFIRMEDFRAUD`                       |
| `transactionAmount`   | String | Amount in decimal format (for example, "150.00")                   |
| `transactionCurrency` | String | ISO 4217 currency code (for example, "USD")                        |
| `dateSubmitted`       | String | Date alert was submitted (YYYY-MM-DD)                              |
| `customerName`        | String | Name of customer                                                   |
| `cardLastFour`        | String | Last four digits of card                                           |
| `merchantName`        | String | Your merchant name                                                 |
| `transactionRef`      | String | Your transaction reference                                         |
| `transactionDate`     | String | Date of transaction (YYYY-MM-DD)                                   |
| `acquirerReference`   | String | Card issuer reference                                              |

*** ** * ** ***

## Step 2: Parse and Process Alerts {#step-2-parse-and-process-alerts}

After retrieving alerts, parse the response and extract key information:

```java
// Example: Java with Jackson
ObjectMapper mapper = new ObjectMapper();
JsonNode response = mapper.readTree(alertsJson);

List<String> alertIds = new ArrayList<>();
for (JsonNode alert : response.get("alerts")) {
  String alertId = alert.get("alertId").asText();
  String alertType = alert.get("alertType").asText();
  String amount = alert.get("transactionAmount").asText();
  
  // Store for later acknowledgement
  alertIds.add(alertId);
  
  // Investigate the transaction asynchronously
  investigateTransaction(alertId, alertType, amount);
}
```

*** ** * ** ***

## Step 3: Acknowledge Alerts {#step-3-acknowledge-alerts}

Once you've parsed the alerts, acknowledge receipt to prevent re-delivery:

### Request {#request-1}

```bash
curl --request POST \
  --url 'https://sandbox.api.ethocaweb.com/ethoca/alerts/merchants/alerts/acknowledges' \
  --header 'Authorization: OAuth oauth_consumer_key="YOUR_CONSUMER_KEY", oauth_signature_method="RSA-SHA256", oauth_signature="...", oauth_timestamp="...", oauth_nonce="..."' \
  --header 'Content-Type: application/json' \
  --data '{
    "acknowledgements": [
      {
        "alertId": "ALERT_ID_001",
        "status": "SUCCESS"
      },
      {
        "alertId": "ALERT_ID_002",
        "status": "SUCCESS"
      }
    ]
  }'
```

#### Request Fields {#request-fields}

|   Field   |  Type  | Required |               Description                |
|-----------|--------|----------|------------------------------------------|
| `alertId` | String | Yes      | The alert ID from the retrieval response |
| `status`  | String | Yes      | Always use `SUCCESS` to confirm receipt  |

### Response {#response-1}

```json
{
  "acknowledgements": [
    {
      "alertId": "ALERT_ID_001",
      "status": "SUCCESS"
    },
    {
      "alertId": "ALERT_ID_002",
      "status": "SUCCESS"
    }
  ]
}
```

#### Handling Acknowledgement Errors {#handling-acknowledgement-errors}

If an acknowledgement fails, check the `Errors` envelope:

```json
{
  "Errors": {
    "Error": [
      {
        "Source": "API",
        "ReasonCode": "VALIDATION_FAILURE",
        "Description": "Acknowledge should be Unique",
        "Recoverable": false,
        "Details": "Alert ID ALERT_ID_001 appears twice in the request"
      }
    ]
  }
}
```

**Resolution:** Remove duplicates and retry.

*** ** * ** ***

## Step 4: Investigate and Submit Outcomes {#step-4-investigate-and-submit-outcomes}

After acknowledgement, investigate each alert asynchronously. You have **up to 24 hours** to submit investigation outcomes.

See [Outcome API Tutorial](https://static.developer.mastercard.com/content/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/pull-api-tutorial/outcome-api-tutorial.md) for detailed outcome submission examples.

*** ** * ** ***

## Common Patterns {#common-patterns}

### Idempotent Alert Handling {#idempotent-alert-handling}

If you receive duplicate alerts (due to retries), handle idempotently:

```java
// Store processed alert IDs in a database or cache
Set<String> processedAlerts = getProcessedAlertIds();

for (Alert alert : alerts) {
  if (processedAlerts.contains(alert.getAlertId())) {
    // Skip re-processing
    continue;
  }
  
  // Process alert
  investigateAlert(alert);
  processedAlerts.add(alert.getAlertId());
}
```

### Batch Size Management {#batch-size-management}

The API returns a maximum of 1,000 alerts per request. For large deployments:

```java
// Paginate through results
int pageSize = 100; // Process 100 at a time
int offset = 0;

while (true) {
  List<Alert> batch = retrieveAlerts(offset, pageSize);
  if (batch.isEmpty()) break;
  
  processBatch(batch);
  offset += pageSize;
}
```

### Error Handling and Retries {#error-handling-and-retries}

Always check the `Recoverable` flag before retrying:

```java
if (error.isRecoverable()) {
  // Implement exponential backoff
  long backoffMs = 1000 * (long) Math.pow(2, retryCount);
  Thread.sleep(backoffMs);
  retry();
} else {
  // Log and fail
  logger.error("Permanent error: " + error.getDescription());
}
```

*** ** * ** ***

## Next Steps {#next-steps}

* Review [Outcome API Tutorial](https://static.developer.mastercard.com/content/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/pull-api-tutorial/outcome-api-tutorial.md) to submit investigation results
* See [Testing](https://developer.mastercard.com/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/testing/index.md) for comprehensive test scenarios
* Check [Codes \& Formats](https://developer.mastercard.com/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/code-and-formats/index.md) for error code reference
* Visit [API Reference](https://developer.mastercard.com/ethoca-alerts-for-merchants/documentation/tutorials-and-guides/api-reference/index.md) for complete endpoint documentation
