# Usage

### Creating an API context

In order to start making calls with the bunq API, you must first register your API key and device, and create a session. In the SDKs, we group these actions and call it "creating an API context". The context can be created by using the following code snippet:

```java
ApiContext apiContext = ApiContext.create(
    ApiEnvironmentType.SANDBOX,
    sandboxUser.getApiKey(),
    "Your Device Description"
);
apiContext.save("bunq-config.conf");

BunqContext.loadApiContext(apiContext); //load the API context to use in your app
```

{% hint style="warning" %}
**Please note:** initialising your application is a heavy task and it is recommended to do it only once per device.
{% endhint %}

**PSD2**

It is possible to create an ApiContext as PSD2 Service Provider. Although this might seem a complex task, we wrote some helper implementations to get you started. You need to create a certificate and private key to get you started. Our sandbox environment currently accepts all certificates, if these criteria are met:

* Up to 64 characters
* PISP and/or AISP used in the end.

Make sure you have your unique eIDAS certificate number and certificates ready when you want to perform these tasks on our production environment.

Creating a PSD2 context is very easy:

```java
ApiContext apiContext = ApiContext.createForPsd2(
    ENVIRONMENT_TYPE,
    SecurityUtils.getCertificateFromFile(PATH_TO_CERTIFICATE),
    SecurityUtils.getPrivateKeyFromFile(PATH_TO_PRIVATE_KEY),
    new Certificate[]{
            SecurityUtils.getCertificateFromFile(PATH_TO_CERTIFICATE_CHAIN)
    },
    DESCRIPTION
)
```

This context can be saved the same way as a normal ApiContext. After creating this context, create an OAuth client to get your users to grant you access. For a more detailed example, check the [tinker\_java](https://github.com/bunq/tinker_java/) repository.

**Safety considerations**

The file storing the context details (i.e. `bunq.conf`) is a key to your account. Anyone having access to it is able to perform any Public API actions with your account. Therefore, we recommend choosing a truly safe place to store it.

#### Making API calls

There is a class for each endpoint. Each class has functions for each supported action. These actions can be `create`, `get`, `update`, `delete` and `list`.

When making calls, The `userId` and `monetaryAccountId` needed to make calls will be determined by the SDK it. When no `monetaryAccountId` has been passed, the SDK will use the first active monetary account it can find. This is normally the monetary account used for billing.

Before you make a call, make sure that you have loaded `ApiContext` in to the `BunqContext`.

### Core Functionalities

#### Managing Monetary Accounts

**Create a new monetary account:**

```java
// Create a new EUR bank account with a description
Integer accountId = MonetaryAccountBankApiObject.create(
    "EUR",                    // Currency code    
    "Account Description"     // Description for the account
).getValue();                 // Returns the new account ID
```

**Close a monetary account:**

```java
// Close an existing monetary account
MonetaryAccountBankApiObject.update(
    accountId,                // ID of the account to close    
    null,                     // No change to currency    
    null,                     // No change to description    
    null,                     // No change to daily limit    
    "CANCELLED",              // New status for the account    
    "REDEMPTION_VOLUNTARY",   // Sub-status explaining the closure reason    
    "OTHER",                  // Reason category    
    "Reason description"      // Detailed explanation
);
```

#### Payments

**Make a payment to another user:**

```java
// Create the amount object with value and currency
AmountObject amount = new AmountObject("0.01", "EUR");  // Amount in EUR

// Create pointer object to specify the recipient
PointerObject recipient = new PointerObject(
    "EMAIL",                  // Type of identifier (EMAIL, PHONE_NUMBER, IBAN)    
    "recipient@example.com"   // The actual identifier value
);

// Execute the payment
PaymentApiObject.create(
    amount,                   // The amount to transfer    
    recipient,                // Who to pay    
    "Payment description"     // Description shown on the transaction
);
```

**Batch payments:**

```java
// Create a list to hold multiple payments
List<PaymentApiObject> payments = new ArrayList<>();

// Add payments to the list
payments.add(new PaymentApiObject(
    new AmountObject("0.01", "EUR"),  // Amount for this payment    
    recipient,                         // Recipient for this payment    
    "Payment description"              // Description for this payment
));

// Execute all payments as a batch
PaymentBatchApiObject.create(payments);  // More efficient than individual calls
```

#### Payment Requests

**Create a payment request:**

```java
// Request money from another user
RequestInquiryApiObject.create(
    new AmountObject("0.01", "EUR"),  // Amount to request    
    recipient,                         // Who to request from    
    "Request description",             // Description of request    
    false,                             // Allow bunqme - false means regular request    
    monetaryAccountId                  // ID of account to receive the money
);
```

**Accept a payment request:**

```java
// Create parameters to filter for pending requests
Map<String, String> params = new HashMap<>();
params.put("status", "PENDING");  // Only get PENDING requests

// Retrieve pending requests
List<RequestResponseApiObject> requests = RequestResponseApiObject.list(
    monetaryAccountId,        // Account ID to check for requests    
    params                    // Filter parameters
).getValue();

// Accept the first pending request
RequestResponseApiObject.update(
    requests.get(0).getId(),  // ID of the request to update    
    monetaryAccountId,        // Account ID that received the request    
    null,                     // No counter-amount needed    
    "ACCEPTED"                // New status - ACCEPTED or REJECTED
);
```

#### Card Management

**Get possible card names:**

```java
// Get all available card names
List<CardNameApiObject> cardNames = CardNameApiObject.list().getValue();

// Get the array of possible names for the first card type
List possibleNames = cardNames.get(0).getPossibleCardNameArray();
```

**Order a new card:**

```java
// Generate a random string for the second line on the card
String secondLine = generateRandomSecondLine();  // Custom method to generate text
String nameOnCard = "YOUR NAME";  // Name to be printed on the card

// Order a new debit card
CardDebitApiObject.create(
    secondLine,               // Text for second line on card    
    nameOnCard,               // Name to appear on card    
    "MASTERCARD",             // Card type    
    "MASTERCARD_DEBIT"        // Product type
);
```

#### File Attachments

**Upload a public attachment:**

<pre class="language-java"><code class="lang-java"><strong>// Create headers for the attachment
</strong><strong>HashMap&#x3C;String, String> headers = new HashMap&#x3C;>();
</strong><strong>BunqHeader.CONTENT_TYPE.addTo(headers, "image/png");  // Specify file type
</strong><strong>BunqHeader.ATTACHMENT_DESCRIPTION.addTo(headers, "Description");  // Add description
</strong><strong>
</strong><strong>// Read file into byte array
</strong><strong>byte[] fileContents = FileUtils.readFileToByteArray(new File("path/to/file.png"));
</strong><strong>
</strong><strong>// Upload the attachment and get its UUID
</strong><strong>String uuid = AttachmentPublicApiObject.create(headers, fileContents).getValue();
</strong></code></pre>

**Retrieve an attachment:**

```java
// Download attachment content using its UUID
byte[] fileContents = AttachmentPublicContentApiObject.list(uuid).getValue();
```

#### Avatar Management

**Create an avatar:**

```java
// First upload an image as a public attachment
String attachmentUuid = uploadAttachment();  // Custom method to upload attachment

// Then create an avatar with the attachment
String avatarUuid = AvatarApiObject.create(attachmentUuid).getValue();  // Returns avatar UUID
```

#### Session Management

**Delete the current session:**

```java
// Delete current session (0 is a dummy session ID, as the actual ID isn't needed)
SessionApiObject.delete(0).getValue();  // Will invalidate current session
```

**Reset a session:**

```java
// Reset the session in your API context
apiContext.resetSession();  // Creates a new session
apiContext.save("bunq-config.conf");  // Save changes to configuration file
```

#### Notification Filters (Webhooks)

**Create a URL notification filter for a monetary account:**

```java
// Create a filter for payment mutations (changes) with a callback URL
NotificationFilterUrlObject filter = new NotificationFilterUrlObject(
    "MUTATION",                      // Event category to trigger on    
    "https://your-callback-url.com"  // URL to receive webhooks
);

// Add filter to a list (API expects a list)
List<NotificationFilterUrlObject> filters = new ArrayList<>();
filters.add(filter);

// Set up the notification filter for a specific account
NotificationFilterUrlMonetaryAccountInternal.createWithListResponse(
    monetaryAccountId,  // Account to monitor    
    filters            // List of filters to apply
);
```

**Create a push notification filter for a user:**

```java
// Create a filter for push notifications about payment mutations
NotificationFilterPushObject filter = new NotificationFilterPushObject("MUTATION");

// Add filter to a list (API expects a list)
List<NotificationFilterPushObject> filters = new ArrayList<>();
filters.add(filter);

// Set up the push notification filter for the current user
NotificationFilterPushUserInternal.createWithListResponse(filters);
```

#### OAuth Authorization

**Create an OAuth authorization URI:**

```java
// Generate an OAuth URL for authorization
String uri = OauthAuthorizationUri.create(
    OauthResponseType.CODE,     // Request an authorization code    
    "your-redirect-uri",        // Where to redirect after authorization    
    new OauthClientApiObject("status"),  // Client information    
    "state"                     // Security state parameter
).getAuthorizationUri();        // Get the complete URI
```

**Creating objects**

With the `create` method you can create new models. This method normally returns the `id` of the created model.

```java
Payment.create(
	new Amount(amount, CURRENCY_EURO),
	new Pointer(POINTER_TYPE_EMAIL, recipient),
	description
);
```

**Reading objects**

Reading objects can be done via the `get` or `list` method.

These type of calls always returns the model or binary data.

```java
Payment.list(
 	monetaryAccountBank.getId(),
    pagination.getUrlParamsCountOnly()
)
```

**Updating objects**

Updating objects through the API goes the same way as creating objects, except that also the object to update identifier (ID or UUID) is needed.

The `update` method will also normally return the `Id` of the updated model.

```java
 MonetaryAccountBank.update(Integer.parseInt(accountId), name);
```

**Deleting objects**

Deleting object can be done via the `delete` method. This method also requires the object identifier which could be an `Id` or `uuid`.

This method normally returns an empty response.

```java
CustomerStatementExport.delete(customerStatementId);
```

### Tips for Using the SDK

1. Always ensure your API context is properly loaded before making API calls
2. Request spending money in the sandbox environment when needed:

   ```java
   // Check if account has less than 10 units of currency
   if (Float.parseFloat(monetaryAccountBank.getBalance().getValue()) < 10) {
       // Request money from the sandbox sugar daddy account    
       RequestInquiryApiObject.create(
               new AmountObject("500", "EUR"),        
               new PointerObject("EMAIL", "sugardaddy@bunq.com"),        
               "Request description",        
               false    
       );
   }
   ```
3. Save your API context after making changes to it
4. Remember to refresh your context periodically for long-running applications:

   ```java
   // Refresh the user context to get latest information
   BunqContext.getUserContext().refreshContext();
   ```
