Inserting data into Position Green via our API
TABLE OF CONTENTS
- Inserting data into Position Green via our API
To import files into Position Green you can send HTTP POST requests to the Import endpoints. Synchronous uploads process immediately, while Queue endpoints enable asynchronous background processing for large datasets.
https://api.positiongreen.com/v1/imports
You must supply valid credentials in the form of an access token or client ID/secret header.
Get available import configurations
Retrieves a list of available import configuration keys for the authenticated tenant.
GET https://api.positiongreen.com/v1/imports
Example Response (200 OK)
[ "ERP_FINANCIAL_IMPORT", "FACILITY_ENERGY_IMPORT", "TRAVEL_DATA_IMPORT" ]
Note about fileType and yearId values
fileType / importConfiguration is a string value that needs to match an existing import-configuration key in Position Green. Available configuration keys can be queried via GET /imports or provided by Position Green upon request.
Optional yearId parameter: All import endpoints accept an optional yearId parameter (UUID). If omitted, data will be imported into the organization's currently active year.
Synchronous Import Endpoints
1. Upload binary file (Multipart Form)
The request must have a multipart/form-data content type with the file sent as file, alongside fileType (string) and optional yearId (UUID).
POST https://api.positiongreen.com/v1/imports
2. Import JSON Payload
For imports configured by Position Green to handle JSON data.
POST https://api.positiongreen.com/v1/imports/json
Request Body Example:
{
"options": {
"importConfiguration": "ERP_FINANCIAL_IMPORT"
},
"payload": "{\"records\": [{\"account\": \"1001\", \"amount\": 520.50}]}",
"yearId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}3. Import Base64 Encoded File
Uploads a file encoded in Base64 string format.
POST https://api.positiongreen.com/v1/imports/base64
Request Body Example:
{
"name": "data-export.xml",
"content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4...",
"fileType": "ERP_FINANCIAL_IMPORT",
"yearId": null
}Handling Synchronous Responses (HTTP 200 OK)
Synchronous import endpoints complete execution before returning a 200 OK status. The response body takes one of two shapes:
- Plain String: If the import completed with nothing to report, the response is the raw JSON string
"ok". - Details Object: If warnings occurred or partial data was skipped, the response returns an object detailing
validationsand executionresult.
Example Response Body (With Warnings / Partial Import):
{
"validations": [
{
"severity": "Warning",
"message": "The value could not be imported as a number.",
"rowNumber": 42,
"columnName": "Energy consumption",
"rowImported": false
}
],
"result": {
"outcome": "Partial",
"nbrOfUpdatedRegistrations": 4,
"nbrOfImportedValues": 118,
"nbrOfSkippedValues": 6,
"nbrOfSkippedSourceRows": 2,
"nbrOfAddedSuppliers": 0,
"nbrOfUpdatedSuppliers": 0,
"nbrOfSkippedSuppliers": 0
}
}Validations Object Schema
Contains one entry per row or value that could not be imported. Successful rows are omitted.
| Field | Type | Description |
severity | string | Indicates severity level: Info, Warning, or Error. |
message | string | Human-readable explanation of why the record failed. |
rowNumber | integer | 1-based row number in your submitted file. |
columnName | string | Column name as formatted in your source file. |
rowImported | boolean (optional) | Set to false when the whole row was skipped. Omitted when only a single value was rejected while the rest of the row imported. |
Result Object Schema
Summarizes data modifications applied to your organization.
| Field | Type | Description |
outcome | string | Full (everything written), Partial (some data skipped), or NothingImported (all data rejected). |
nbrOfUpdatedRegistrations | integer | Registrations written. A registration holds multiple values for one entity unit per period. |
nbrOfImportedValues | integer | Individual datapoints written. Empty submitted values are excluded. |
nbrOfSkippedValues | integer | Datapoints dropped (e.g., target registration does not exist, is confirmed, or locked). |
nbrOfSkippedSourceRows | integer | File rows dropped entirely prior to writing (unmapped rows or total row value rejection). |
nbrOfAddedSuppliers | integer | New suppliers created during this operation. |
nbrOfUpdatedSuppliers | integer | Existing suppliers modified during this operation. |
nbrOfSkippedSuppliers | integer | Suppliers in source file that were not written. |
Note: The count fields measure distinct data metrics and must not be added together. Check outcome for status logic and validations to resolve data issues.
Background / Queued Import Endpoints
For large datasets, use the /queue endpoints. These endpoints return immediately with an HTTP 202 Accepted status and an importId. You can poll the status endpoint to track progress.
| Endpoint | Format | Description |
POST /imports/queue | multipart/form-data | Queues a binary file upload for background execution. |
POST /imports/queue/json | application/json | Queues a JSON payload for background execution. |
POST /imports/queue/base64 | application/json | Queues a Base64 encoded file for background execution. |
Queued Response Example (202 Accepted)
{
"importId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
}Checking Queued Import Status
Poll this endpoint using the importId returned from a /queue endpoint to check processing status.
GET https://api.positiongreen.com/v1/imports/status/{importId}Path Parameters
| Name | Type | Description |
| importId* | string (uuid) | Required. The identifier returned when the import was queued. |
Status Response Example (200 OK)
{
"importId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"status": "Done",
"startedAt": "2026-02-01T10:00:00Z",
"finishedAt": "2026-02-01T10:02:15Z",
"details": {
"validations": [
{
"severity": "Warning",
"message": "The value could not be imported as a number.",
"rowNumber": 42,
"columnName": "Energy consumption",
"rowImported": false
}
],
"result": {
"outcome": "Partial",
"nbrOfUpdatedRegistrations": 4,
"nbrOfImportedValues": 118,
"nbrOfSkippedValues": 6,
"nbrOfSkippedSourceRows": 2,
"nbrOfAddedSuppliers": 0,
"nbrOfUpdatedSuppliers": 0,
"nbrOfSkippedSuppliers": 0
}
}
}Possible status values: Queued, InProgress, Done, Failed.
Example 1 - Import a file to Position Green API using HttpClient
namespace TestClient;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
public class Program
{
private static string apiUrl = "https://api.positiongreen.com/v1/imports";
private static string loginUrl = "https://login.positiongreen.com/connect/token";
public static async Task Main()
{
var token = await RequestToken("clientid", "clientsecret");
var fileType = "ERP_FINANCIAL_IMPORT";
await UploadFile(token, "data.xml", fileType);
}
private static async Task<string> RequestToken(string clientId, string clientSecret)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.BaseAddress = new Uri(loginUrl);
var data = new Dictionary<string, string>
{
{ "client_id", clientId },
{ "client_secret", clientSecret },
{ "grant_type", "client_credentials" },
};
var response = await client.PostAsync("/connect/token", new FormUrlEncodedContent(data));
var token = await response.Content.ReadFromJsonAsync<Token>();
return token.access_token;
}
static async Task UploadFile(string token, string file, string fileType)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var form = new MultipartFormDataContent();
var fileData = await File.ReadAllBytesAsync(file);
var byteArrayContent = new ByteArrayContent(fileData);
byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("text/xml");
form.Add(byteArrayContent, "file", file);
form.Add(new StringContent(fileType), "fileType");
var response = await client.PostAsync(apiUrl, form);
var bodyString = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Error {response.StatusCode}: {bodyString}");
}
// Handle string response ("ok") vs JSON payload details
if (bodyString.Trim('"').Equals("ok", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Import completed cleanly with nothing to report.");
}
else
{
using var doc = JsonDocument.Parse(bodyString);
var root = doc.RootElement;
if (root.TryGetProperty("result", out var result))
{
var outcome = result.GetProperty("outcome").GetString();
Console.WriteLine($"Import completed with outcome: {outcome}");
}
}
}
}
public class Token
{
public string access_token { get; set; }
}Explore the full Import section on our Swagger page.
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article