# Deliveries

Upload files for batch processing and manage file-based integrations. This section covers uploading invoice files, agreement files, and payment files for bulk processing.

## Overview

The Deliveries endpoint allows you to upload files for batch processing. This is useful for:

* **Bulk invoice creation** - Upload multiple invoices at once
* **Agreement management** - Upload agreement files for batch processing
* **Payment reconciliation** - Upload payment files for reconciliation
* **File-based integrations** - Integrate with existing file-based systems

## File Upload Process

### Two-Step Upload Process

The delivery system supports a two-step upload process for large files:

1. **Create delivery** - Submit delivery metadata without file content
2. **Upload file** - Upload the actual file using the provided upload URL

### Step 1: Create Delivery

```http
POST https://api.farpay.io/v2/deliveries
```

**Request Body (without file data):**

```json
{
  "DeliveryType": "Invoice",
  "DeliveryFormat": "XML",
  "File": {
    "Filename": "invoices_january.xml"
  }
}
```

**Response with Upload URL:**

```json
{
  "Id": 1234,
  "Created": "2023-01-15T10:30:00Z",
  "DeliveryType": "Invoice",
  "DeliveryStatus": "New",
  "ErrorMessage": null,
  "FileUploadUri": "https://farpay.blob.core.windows.net/uploads/upload_1234?sv=2020-08-04&sr=b&sig=...&sp=w&se=2023-01-15T11:00:00Z&spr=https"
}
```

### Step 2: Upload File

Use the `FileUploadUri` to upload the actual file:

```http
PUT {FileUploadUri}
```

**Required Headers:**

```
x-ms-blob-type: blockblob
Content-Type: application/octet-stream
```

**Request Body:**

```
[Binary file content]
```

**Important Notes:**

* **30-minute timeout** - Upload URLs expire after 30 minutes
* **PUT method only** - Only PUT requests are accepted
* **Binary content** - Send raw file content, not base64 encoded
* **Required header** - `x-ms-blob-type: blockblob` is mandatory

## API Endpoints

### Get All Deliveries

Retrieve all deliveries with optional filtering.

```http
GET https://api.farpay.io/v2/deliveries
```

**Query Parameters:**

* `status` (optional) - Filter by status: New, Processing, Ok, Error
* `type` (optional) - Filter by type: Invoice, Agreement, Payment
* `direction` (optional) - Filter by direction: CompanyToFarPay, FarPayToCompany
* `fromDate` (optional) - Start date for filtering
* `toDate` (optional) - End date for filtering

**Response Example:**

```json
{
  "DeliveryReferences": [
    {
      "Id": 1234,
      "Created": "2023-01-15T10:30:00Z",
      "DeliveryType": "Invoice",
      "DeliveryStatus": "Ok",
      "ErrorMessage": null,
      "FileUploadUri": null
    }
  ],
  "Count": 1
}
```

### Get Single Delivery

Retrieve detailed information for a specific delivery.

```http
GET https://api.farpay.io/v2/deliveries/{id}?includeFile=true
```

**Parameters:**

* `id` (path) - The delivery's unique identifier
* `includeFile` (query) - Include file content in response (true/false)

**Response Example:**

```json
{
  "Id": 1234,
  "DeliveryFormat": "XML",
  "DeliveryStatus": "Ok",
  "ErrorMessage": null,
  "DeliveryType": "Invoice",
  "InvoiceNumber": "INV-001",
  "File": {
    "Filename": "invoices_january.xml",
    "Data": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>..."
  }
}
```

### Update Delivery Status

Mark a delivery as processed.

```http
PUT https://api.farpay.io/v2/deliveries/{id}
```

**Request Body:**

```json
{
  "Id": 1234,
  "DeliveyStatus": "Ok",
  "DeliveryType": "Invoice",
  "DeliveryFormat": "XML"
}
```

## Delivery Properties

### Core Properties

| Property         | Type     | Description                                    |
| ---------------- | -------- | ---------------------------------------------- |
| `Id`             | integer  | Unique delivery identifier                     |
| `Created`        | datetime | Delivery creation timestamp                    |
| `DeliveryType`   | string   | Type of delivery (Invoice, Agreement, Payment) |
| `DeliveryStatus` | string   | Current processing status                      |
| `ErrorMessage`   | string   | Error message (if any)                         |
| `FileUploadUri`  | string   | File upload URL (if applicable)                |

### Delivery Details Properties

| Property         | Type   | Description                   |
| ---------------- | ------ | ----------------------------- |
| `DeliveryFormat` | string | File format (XML, JSON, etc.) |
| `InvoiceNumber`  | string | Associated invoice number     |
| `File`           | object | File information and content  |

### File Properties

| Property   | Type   | Description                                 |
| ---------- | ------ | ------------------------------------------- |
| `Filename` | string | Original filename                           |
| `Data`     | string | File content (base64 encoded when included) |

## Delivery Types

| Type        | Description     | Use Case                   |
| ----------- | --------------- | -------------------------- |
| `Invoice`   | Invoice files   | Bulk invoice creation      |
| `Agreement` | Agreement files | Batch agreement processing |
| `Payment`   | Payment files   | Payment reconciliation     |

## Delivery Status

| Status       | Description                               |
| ------------ | ----------------------------------------- |
| `New`        | Delivery created, waiting for file upload |
| `Processing` | File uploaded, being processed            |
| `Ok`         | Processing completed successfully         |
| `Error`      | Processing failed                         |

## Delivery Direction

| Direction         | Description                            |
| ----------------- | -------------------------------------- |
| `CompanyToFarPay` | Files sent from your company to FarPay |
| `FarPayToCompany` | Files sent from FarPay to your company |

## File Upload Examples

### Direct Upload (Small Files)

For small files, you can include the file content directly:

```javascript
const fileContent = fs.readFileSync('invoices.xml');
const base64Data = fileContent.toString('base64');

const delivery = {
  DeliveryType: "Invoice",
  DeliveryFormat: "XML",
  File: {
    Filename: "invoices.xml",
    Data: base64Data
  }
};

const response = await fetch('https://api.farpay.io/v2/deliveries', {
  method: 'POST',
  headers: {
    'X-API-KEY': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(delivery)
});
```

### Two-Step Upload (Large Files)

For large files, use the two-step process:

```javascript
// Step 1: Create delivery
const delivery = {
  DeliveryType: "Invoice",
  DeliveryFormat: "XML",
  File: {
    Filename: "large_invoices.xml"
  }
};

const response = await fetch('https://api.farpay.io/v2/deliveries', {
  method: 'POST',
  headers: {
    'X-API-KEY': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(delivery)
});

const deliveryInfo = await response.json();

// Step 2: Upload file
const fileContent = fs.readFileSync('large_invoices.xml');

const uploadResponse = await fetch(deliveryInfo.FileUploadUri, {
  method: 'PUT',
  headers: {
    'x-ms-blob-type': 'blockblob',
    'Content-Type': 'application/octet-stream'
  },
  body: fileContent
});

if (uploadResponse.ok) {
  console.log('File uploaded successfully');
} else {
  console.error('File upload failed');
}
```

## File Format Specifications

### XML Invoice Format

```xml
<?xml version="1.0" encoding="UTF-8"?>
<invoices>
  <invoice>
    <customerNumber>12345</customerNumber>
    <invoiceNumber>INV-001</invoiceNumber>
    <amount>125.00</amount>
    <dueDate>2023-02-15</dueDate>
    <description>Monthly subscription</description>
  </invoice>
</invoices>
```

### OIOUBL Format

```xml
<?xml version="1.0" encoding="UTF-8"?>
<cac:Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
  <cbc:ID>INV-001</cbc:ID>
  <cbc:IssueDate>2023-01-15</cbc:IssueDate>
  <cbc:DueDate>2023-02-15</cbc:DueDate>
  <cac:AccountingCustomerParty>
    <cac:Party>
      <cac:PartyIdentification>
        <cbc:ID>12345</cbc:ID>
      </cac:PartyIdentification>
    </cac:Party>
  </cac:AccountingCustomerParty>
</cac:Invoice>
```

## Delivery Monitoring

### Check Delivery Status

```javascript
// Monitor delivery processing
const deliveryId = 1234;
const response = await fetch(`https://api.farpay.io/v2/deliveries/${deliveryId}?includeFile=false`, {
  headers: {
    'X-API-KEY': 'your-api-key',
    'Accept': 'application/json'
  }
});

const delivery = await response.json();

if (delivery.DeliveryStatus === 'Processing') {
  console.log('File is being processed...');
} else if (delivery.DeliveryStatus === 'Ok') {
  console.log('File processed successfully');
} else if (delivery.DeliveryStatus === 'Error') {
  console.log('Processing failed:', delivery.ErrorMessage);
}
```

### Get Recent Deliveries

```javascript
// Get deliveries from last 7 days
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

const response = await fetch(`https://api.farpay.io/v2/deliveries?fromDate=${sevenDaysAgo.toISOString().split('T')[0]}`, {
  headers: {
    'X-API-KEY': 'your-api-key',
    'Accept': 'application/json'
  }
});

const deliveries = await response.json();

// Check for errors
const failedDeliveries = deliveries.DeliveryReferences.filter(d => d.DeliveryStatus === 'Error');
if (failedDeliveries.length > 0) {
  console.log('Failed deliveries:', failedDeliveries);
}
```

## Error Handling

### Common Error Responses

| Status Code | Description                               |
| ----------- | ----------------------------------------- |
| `400`       | Bad request - Invalid delivery data       |
| `401`       | Unauthorized - Invalid API key            |
| `404`       | Not found - Delivery doesn't exist        |
| `403`       | Forbidden - Cannot change delivery status |

### Common Delivery Errors

| Error                     | Description                   | Solution                |
| ------------------------- | ----------------------------- | ----------------------- |
| `Invalid file format`     | Unsupported file format       | Check supported formats |
| `File too large`          | File exceeds size limits      | Use two-step upload     |
| `Invalid XML structure`   | Malformed XML content         | Validate XML structure  |
| `Missing required fields` | Required data missing         | Check file content      |
| `Processing timeout`      | File processing took too long | Retry with smaller file |
| `Upload URL expired`      | Upload URL expired            | Create new delivery     |

## Best Practices

### File Upload

1. **Use appropriate upload method** - Direct upload for small files, two-step for large files
2. **Validate file content** - Check file format and structure before upload
3. **Handle upload timeouts** - Upload URLs expire after 30 minutes
4. **Monitor upload progress** - Check delivery status after upload
5. **Implement retry logic** - Retry failed uploads with exponential backoff

### File Processing

1. **Monitor processing status** - Check delivery status regularly
2. **Handle errors gracefully** - Log and handle processing errors
3. **Validate results** - Verify processing results match expectations
4. **Keep file backups** - Maintain local copies of uploaded files

### Performance

1. **Optimize file size** - Keep files reasonably sized for faster processing
2. **Use appropriate formats** - Specify delivery format for faster processing
3. **Batch operations** - Group related files in single deliveries when possible
4. **Monitor system load** - Avoid overwhelming the system with too many uploads

## Integration Examples

### Batch Invoice Upload

```javascript
// Upload multiple invoice files
const invoiceFiles = [
  'invoices_january.xml',
  'invoices_february.xml',
  'invoices_march.xml'
];

for (const filename of invoiceFiles) {
  const fileContent = fs.readFileSync(filename);
  const base64Data = fileContent.toString('base64');
  
  const delivery = {
    DeliveryType: "Invoice",
    DeliveryFormat: "XML",
    File: {
      Filename: filename,
      Data: base64Data
    }
  };
  
  try {
    const response = await fetch('https://api.farpay.io/v2/deliveries', {
      method: 'POST',
      headers: {
        'X-API-KEY': 'your-api-key',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(delivery)
    });
    
    const result = await response.json();
    console.log(`Uploaded ${filename}:`, result.Id);
  } catch (error) {
    console.error(`Failed to upload ${filename}:`, error);
  }
}
```

### Monitor Batch Processing

```javascript
// Monitor all deliveries
const response = await fetch('https://api.farpay.io/v2/deliveries', {
  headers: {
    'X-API-KEY': 'your-api-key',
    'Accept': 'application/json'
  }
});

const deliveries = await response.json();

const statusCounts = {
  New: 0,
  Processing: 0,
  Ok: 0,
  Error: 0
};

deliveries.DeliveryReferences.forEach(delivery => {
  statusCounts[delivery.DeliveryStatus]++;
});

console.log('Delivery status summary:', statusCounts);

// Handle errors
if (statusCounts.Error > 0) {
  const errors = deliveries.DeliveryReferences.filter(d => d.DeliveryStatus === 'Error');
  console.log('Failed deliveries:', errors);
}
```

## Related Endpoints

* [Invoices](invoices#) - Manage individual invoices
* [Agreements](agreements#) - Handle payment agreements
* [Payments](payments#) - Track payment processing
* [Customers](customers#) - Manage customer data

# Deliveries

This endpoint supports slipping XML file-payloads as files into FarPay, simular to the SFTP connection.
With this endpoint you can ship off a file, with filename and content.

The Use-Case scenarios are:

* Insert a new delivery with an attached file
* Get the existing delivery (Status and details)
* Get a collection of deliveries, filtered by status, start- and enddate.

Remark that [all requests must have](how-to-use#) an `X-API-KEY`, and a `Accept` mentioned in the header of the request.

# Insert a new Delivery

Use `POST` to the endpoint `https://api.farpay.io/{version}/deliveries` to insert a file with following data:

## Parameters

There are two parameters, that are governing the inserted type.

### DeliveryFormat

| Value               | Description                     |
| ------------------- | ------------------------------- |
| `xml`  or  `oioxml` | XML format                      |
| `oioubl`            | OIOUBL format                   |
| `601`               | BS Payment file                 |
| `605`               | BS Agreement                    |
| `rd07`              | Domestic format (Faroe Islands) |
| `farpayxml`         | FarPay propritary format        |

*Remark!* The if the format is not set in the request, the receiver will try to determine the format of the attached file.
It will do a right classification if the file has a rootnode of `agreements` or `statement` or `bill`.

### DeliveryType

The delivery type, is derived and determine from the DeliveryFormat.
The following table shows the DeliveryType, that is derived from the DeliveryFormat.

| DeliveryFormat                          | DeliveryType                   |
| --------------------------------------- | ------------------------------ |
| `xml`, `oioxml`, `oioubl`,601`, `rd07\` | Invoice                        |
| `605`                                   | Agreement                      |
| `farpayxml`                             | the content indicates the type |

As JSON:

```javascript
{
  "DeliveryType": "TransmissionReceipt",
  "File": {
    "Filename": "mySuperFileName.xml",
    "Data": "<base64 file content>"
  }
}
```

As XML:

```xml
<?xml version="1.0"?>
<Delivery>
  <DeliveryType>TransmissionReceipt</DeliveryType>
  <File>
    <Filename>mySuperFileName.xml</Filename>
    <Data>base64-fileContent</Data>
  </File>
</Delivery>
```

When the data has successfully posted into the endpoint, the result is a `Delivery` that is presented by following:

```javascript
{
  "Id": <unique fileId>,
  "Created": "2018-10-02T16:19:42.001Z",
  "DeliveryType": "TransmissionReceipt",
  "DeliveryStatus": "New", "Processing" "Ok" | "Error",
  "ErrorMessage": "<Description of the error>" | ""
}
```

# Get the existing delivery

This endpoints gives you an elaborated detail of the delivery, including the file data if wanted.
A single delivery is available as `GET` from `https://api.farpay.io/{version}/deliveries/{deliveryId}?includeFile=false` or
`https://api.farpay.io/{version}/deliveries/{deliveryId}?includeFile=true`

The `File` is null when not included in the request

```javascript
{
  "Id": <unique delivery id>,
  "DeliveryFormat": "string",
  "DeliveryStatus": "string",
  "ErrorMessage": "string",
  "DeliveryType": "string",
  "File": {
    "Filename": "string",
    "Data": "<64 based string of the file content>" 
  } | null
}
```

# Get a collection of deliveries

The collection is wrapped in a container, that in addition the the collection of deliveries, holds the
count of how many deliveries you have retreived.
The endpoint is available from a `GET` from `https://api.farpay.io/{version}/deliveries`
with the optional filters of:

* `status`
* `fromDate`
* `toDate`

Example a return container:

```JSON
{
  "DeliveryReferences": [
      "Id": 1234,
      "Created": "2018-10-12T04:46:33",
      "DeliveryType": "FarPayXmlType",
      "DeliveryStatus": "Error",
      "ErrorMessage": "Line number 1 Current format is ither not set or not supported. Please make sure that the PrepareFactory method is called"
    },
    {
      "Id": 1235,
      "Created": "2018-09-05T11:02:20.00",
      "DeliveryType": "FarPayXmlType",
      "DeliveryStatus": "Ok",
      "ErrorMessage": ""
    },
  ],
  "Count": 2
}
```