Position Green API: Import data

Modified on Thu, 27 Aug at 11:23 AM

Inserting data into Position Green via our API 


TABLE OF CONTENTS


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 validations and execution result.

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.

FieldTypeDescription
severitystringIndicates severity level: Info, Warning, or Error.
messagestringHuman-readable explanation of why the record failed.
rowNumberinteger1-based row number in your submitted file.
columnNamestringColumn name as formatted in your source file.
rowImportedboolean (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.

FieldTypeDescription
outcomestringFull (everything written), Partial (some data skipped), or NothingImported (all data rejected).
nbrOfUpdatedRegistrationsintegerRegistrations written. A registration holds multiple values for one entity unit per period.
nbrOfImportedValuesintegerIndividual datapoints written. Empty submitted values are excluded.
nbrOfSkippedValuesintegerDatapoints dropped (e.g., target registration does not exist, is confirmed, or locked).
nbrOfSkippedSourceRowsintegerFile rows dropped entirely prior to writing (unmapped rows or total row value rejection).
nbrOfAddedSuppliersintegerNew suppliers created during this operation.
nbrOfUpdatedSuppliersintegerExisting suppliers modified during this operation.
nbrOfSkippedSuppliersintegerSuppliers 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.

EndpointFormatDescription
POST /imports/queuemultipart/form-dataQueues a binary file upload for background execution.
POST /imports/queue/jsonapplication/jsonQueues a JSON payload for background execution.
POST /imports/queue/base64application/jsonQueues 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

NameTypeDescription
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

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article