# Response codes (/docs/direct-debit/response-codes)

HTTP status codes and error handling for the Precium API.

## HTTP Status Codes [#http-status-codes]

| Code | Type | Description |
|---|---|---|
| `200` | Successful | Request processed successfully |
| `201` | Created | Resource created successfully |
| `204` | No Content | Request processed, resource removed |
| `400` | Bad Request | Invalid request structure or data |
| `401` | Unauthorized | Invalid or expired access token |
| `403` | Forbidden | Insufficient permissions |
| `404` | Not Found | Requested resource not found |
| `409` | Conflict | Resource conflict (e.g., duplicate reference) |
| `500` | Internal Server Error | Server error - contact Precium support |

## Success Responses [#success-responses]

### 200 OK [#200-ok]

Returned for successful GET requests and updates.

```json
{
  "id": "8f4a6b0f-fa9b-4f45-8e19-b75c1a70432a",
  "status": "COMPLETED",
  ...
}
```

### 201 Created [#201-created]

Returned when a resource is successfully created.

```json
{
  "id": "new-resource-id",
  "status": "PENDING",
  ...
}
```

### 204 No Content [#204-no-content]

Returned when a resource is successfully deleted. No response body.

## Error Responses [#error-responses]

### 400 Bad Request [#400-bad-request]

Invalid request data. Check required fields and formats.

```json
{
  "value": {
    "Message": "Validation error: field 'accountNumber' is required"
  },
  "statusCode": 400
}
```

**Common causes:**

- Missing required fields
- Invalid field formats
- Invalid enum values
- Business rule violations

### 401 Unauthorized [#401-unauthorized]

Invalid or expired access token.

```json
{
  "message": "Unauthorized"
}
```

**Resolution:** Request a new access token.

### 403 Forbidden [#403-forbidden]

Insufficient permissions for the requested operation.

```json
{
  "message": "Forbidden"
}
```

**Resolution:** Contact Precium support to verify account permissions.

### 404 Not Found [#404-not-found]

Requested resource does not exist.

```json
{
  "message": "Resource not found"
}
```

**Common causes:**

- Invalid resource ID
- Resource deleted or expired

### 409 Conflict [#409-conflict]

Resource conflict, typically duplicate data.

```json
{
  "message": "Duplicate external reference"
}
```

**Common causes:**

- Duplicate `externalReference`
- Duplicate `contractReference`

### 500 Internal Server Error [#500-internal-server-error]

Server-side error.

```json
{
  "message": "Internal server error"
}
```

**Resolution:** Contact Precium support with request details.

## Mandate Status Codes [#mandate-status-codes]

### EFT Mandate Statuses [#eft-mandate-statuses]

| Status | Description |
|---|---|
| `ACTIVE` | Mandate is active and can be used for collections |
| `SUSPENDED` | Mandate temporarily suspended |
| `CANCELLED` | Mandate cancelled, no further collections |
| `EXPIRED` | Mandate has expired |

### DebiCheck Mandate Statuses [#debicheck-mandate-statuses]

| Status | Description |
|---|---|
| `NEW` | Mandate created, not yet submitted |
| `PENDING_AUTHENTICATION` | Awaiting customer authentication |
| `COMPLETED` | Successfully authenticated |
| `AUTH_FAILURE` | Authentication failed or rejected |
| `CANCELLED` | Mandate cancelled |
| `SUSPENDED` | Mandate temporarily suspended |

## Collection Status Codes [#collection-status-codes]

| Status | Description |
|---|---|
| `PENDING` | Collection submitted, awaiting processing |
| `PROCESSING` | Being processed by bank |
| `COMPLETED` | Collection successful |
| `UNPAID` | Collection failed |
| `DISPUTED` | Customer disputed the collection |
| `CANCELLED` | Collection cancelled before processing |

### Unpaid Reason Codes [#unpaid-reason-codes]

When a collection returns `UNPAID`, additional information may include:

| Code | Description |
|---|---|
| `INSUFFICIENT_FUNDS` | Not enough funds in account |
| `ACCOUNT_CLOSED` | Account has been closed |
| `ACCOUNT_NOT_FOUND` | Account does not exist |
| `PAYMENT_STOPPED` | Customer stopped the payment |
| `NOT_PROVIDED_FOR` | Account holder rejected debit |

## Payment Status Codes [#payment-status-codes]

| Status | Description |
|---|---|
| `PENDING` | Payment submitted, awaiting processing |
| `PROCESSING` | Being processed by bank |
| `COMPLETED` | Payment successful |
| `FAILED` | Payment failed |
| `CANCELLED` | Payment cancelled |

## Bank Account Verification Codes [#bank-account-verification-codes]

When `verifyAccount: true` fails:

```json
{
  "value": {
    "Message": "Debtor account verification failure: details={\"AccountExists\":true,\"AccountIsOpen\":false,\"AccountTypeMatches\":null,\"IdNumberMatches\":null,\"AccountAcceptsDebits\":null}"
  },
  "statusCode": 400
}
```

| Field | Description |
|---|---|
| `AccountExists` | Account number exists at bank |
| `AccountIsOpen` | Account is active/open |
| `AccountTypeMatches` | Provided type matches actual |
| `AccountAcceptsDebits` | Account can receive debits |
| `IdNumberMatches` | ID matches account holder |

## Error Handling Best Practices [#error-handling-best-practices]

### Retry Logic [#retry-logic]

```jsx
async function apiRequest(options, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(options.url, options);

      if (response.status === 401) {
        // Refresh token and retry
        await refreshToken();
        continue;
      }

      if (response.status >= 500) {
        // Server error - wait and retry
        await sleep(attempt * 1000);
        continue;
      }

      return response;
    } catch (error) {
      if (attempt === maxRetries) throw error;
      await sleep(attempt * 1000);
    }
  }
}
```

### Logging [#logging]

Log all API responses for debugging:

```jsx
console.log({
  timestamp: new Date().toISOString(),
  endpoint: response.url,
  status: response.status,
  requestId: response.headers.get('x-request-id'),
  body: await response.json()
});
```

### Error Mapping [#error-mapping]

Map API errors to user-friendly messages:

```jsx
const errorMessages = {
  400: 'Invalid request data. Please check your input.',
  401: 'Session expired. Please log in again.',
  403: 'You do not have permission for this action.',
  404: 'The requested resource was not found.',
  409: 'This reference already exists.',
  500: 'An unexpected error occurred. Please try again later.'
};
```

## Contact Support [#contact-support]

If you encounter a `500` status code or persistent errors:

1. Note the request details (endpoint, payload, timestamp)
2. Check for any `x-request-id` in response headers
3. Contact Precium support with this information

**Email:** support@precium.com
