Brief API voor het verzenden van {briefpost} via PostNL

Versnel je briefverzending met de Pingen Brief API. Start direct met onze SDK’s en verstuur binnen no-time via PostNL, met prijzen vanaf € 1,07.

API-documentatie openen
Pingen Letter API met PHP-codevoorbeeld en dashboardweergave

API voor print- en postautomatisering

Onze APi is gratis

Wij geloven in de kracht van procesautomatisering. Daarom bieden we onze API gratis aan.

Meertalige SDK's

Met onze SDK's voor PHP, Python en .Net wordt briefverzending in no-time geïntegreerd!

Ondersteunde betaalsystemen

Print automatisch Zwitserse QR-facturen of SEPA-betalingsopdrachten in Duitsland en Oostenrijk.

Gemaakt voor developers

Een API met duidelijke documentatie, ontwikkeld door experts voor gemakkelijke integratie.

Track & Trace

Pingen biedt realtime updates en transparantie voor elke brief die via de API wordt verzonden.

Genereer inkomsten

Genereer inkomsten door postdienstverlening via PostNL door te verkopen aan klanten.

Simpel starten, snel in gebruik.

De Pingen API is heel gebruiksvriendelijk, waardoor integratie eenvoudig verloopt. We bieden duidelijke documentatie en codevoorbeelden voor een snelle start.

API-documentatie openen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pingen2sdk

pingen2sdk.client_id = "YOUR_OAUTH2_CLIENT_ID"
pingen2sdk.client_secret = "YOUR_OAUTH2_CLIENT_SECRET"

resp = pingen2sdk.OAuth.get_token(
   grant_type = "client_credentials",
   scope = "letter batch webhook organisation_read",
)

try:
   print(
        pingen2sdk.FileUpload(pingen2sdk.APIRequestor(resp["access_token"]))
        .request_file_upload()
        .data
   )
except pingen2sdk.error.PingenError as e:
   print(e.status_code)
   print(e.json_body)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

require __DIR__ . '/vendor/autoload.php';

$provider = new \Pingen\Provider\Pingen(
    array(
        'clientId' => 'YOUR_OAUTH2_CLIENT_ID',
        'clientSecret' => 'YOUR_OAUTH2_CLIENT_SECRET'
    )
);

$accessToken = $provider->getAccessToken('client_credentials');

$lettersEndpoint = (new \Pingen\Endpoints\LettersEndpoint($accessToken))
    ->setOrganisationId('YOUR_ORGANISATION_UUID');

$lettersEndpoint->uploadAndCreate(
    (new \Pingen\Endpoints\DataTransferObjects\Letter\LetterCreateAttributes())
        ->setFileOriginalName('your_filename.pdf')
        ->setAddressPosition('left')
        ->setAutoSend(false),
    fopen('path_to_file.pdf', 'r')
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import json
import requests

url_file_upload = 'https://api.pingen.com/file-upload'
url_letters = 'https://api.pingen.com/organisations/YOUR_ORGANISATION_UUID/letters'
access_token = 'INSERT_YOUR_ACCESS_TOKEN_HERE'

response = requests.get(url_file_upload, headers = {
  'Authorization': 'Bearer {}'.format(access_token),
})
data = json.loads(response.text)['data']
file_url = data['attributes']['url']
file_url_signature = data['attributes']['url_signature']

file = open('path_to_your_file.pdf', 'rb')
requests.put(file_url, data=file)
file.close()

payload = {
  'data': {
    'type': 'letters',
    'attributes': {
      'file_original_name': 'your_filename.pdf',
      'file_url': file_url,
      'file_url_signature': file_url_signature,
      'address_position': 'left',
      'auto_send': False
    }
  }
}

requests.post(
  url_letters,
  json.dumps(payload),
  headers = {
    'Content-Type': 'application/vnd.api+json',
    'Authorization': 'Bearer {}'.format(access_token)
  }
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

$organisationUUID = 'INSERT_YOUR_ORGANISATION_UUID_HERE';
$accessToken = 'INSERT_YOUR_ACCESS_TOKEN_HERE';
$fileOriginalName = 'your_filename.pdf';
$filePath = 'path_to_your_file.pdf';

// Step 1: GET request to retrieve upload URL and signature
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://api.pingen.com/file-upload");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  "Authorization: Bearer $accessToken"
]);

$response = curl_exec($ch);
if (curl_errno($ch)) {
  echo 'Error:' . curl_error($ch);
  exit;
}
curl_close($ch);

$responseData = json_decode($response, true);
if (!isset($responseData['data']['attributes']['url']) || !isset($responseData['data']['attributes']['url_signature'])) {
  echo 'Failed to retrieve URL and signature.';
  exit;
}

$uploadUrl = $responseData['data']['attributes']['url'];
$uploadUrlSignature = $responseData['data']['attributes']['url_signature'];

// Step 2: PUT request to upload the file
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $uploadUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, fopen($filePath, 'r'));
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath));

$response = curl_exec($ch);
if (curl_errno($ch)) {
  echo 'Error:' . curl_error($ch);
  exit;
}
curl_close($ch);

$data = [
  'data' => [
    'type' => 'letters',
    'attributes' => [
      'file_original_name' => $fileOriginalName,
      'file_url' => $uploadUrl,
      'file_url_signature' => $uploadUrlSignature,
      'address_position' => 'left',
      'auto_send' => false,
    ]
  ]
];

// Step 3: POST request to create the letter
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://api.pingen.com/organisations/$organisationUUID/letters");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

$headers = [
  'Content-Type: application/vnd.api+json',
  "Authorization: Bearer $accessToken"
];

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
if (curl_errno($ch)) {
  echo 'Error:' . curl_error($ch);
}
curl_close($ch);

echo $response;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
curl \
  -X GET "https://api.pingen.com/file-upload" \
  -H "Authorization: Bearer INSERT_YOUR_ACCESS_TOKEN_HERE"

# Extract data.attributes.url and data.attributes.url_signature from response

curl -X PUT -T path_to_your_file.pdf "INSERT_URL_FROM_INITIAL_CURL_REQUEST"

curl \
  -X POST "https://api.pingen.com/organisations/INSERT_YOUR_ORGANISATION_UUID_HERE/letters" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Authorization: Bearer INSERT_YOUR_ACCESS_TOKEN_HERE" \
  --data-binary @- << EOF
  {
    "data": { \
      "type": "letters", \
      "attributes": { \
        "file_original_name": "your_filename.pdf", \
        "file_url": "INSERT_URL_FROM_INITIAL_CURL_REQUEST", \
        "file_url_signature": "INSERT_URL_SIGNATURE_FROM_INITIAL_CURL_REQUEST", \
        "address_position": "left", \
        "auto_send": false \
      } \
    } \
  }
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import (
  "bytes"
  "encoding/json"
  "fmt"
  "io"
  "net/http"
  "os"
)

func main() {
  urlFileUpload := "https://api.pingen.com/file-upload"
  urlLetters := "https://api.pingen.com/organisations/YOUR_ORGANISATION_UUID/letters"
  accessToken := "INSERT_YOUR_ACCESS_TOKEN_HERE"

  // Step 1: GET file upload endpoint
  req, err := http.NewRequest("GET", urlFileUpload, nil)
  if err != nil {
    fmt.Println("Error creating GET request:", err)
    return
  }
  req.Header.Set("Authorization", "Bearer "+accessToken)

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error sending GET request:", err)
    return
  }
  defer resp.Body.Close()

  if resp.StatusCode != http.StatusOK {
    fmt.Printf("Failed to fetch file upload data, status: %d\n", resp.StatusCode)
    return
  }

  // Parse the response
  var fileUploadData struct {
    Data struct {
      Attributes struct {
        URL string `json:"url"`
        URLSignature string `json:"url_signature"`
      } `json:"attributes"`
    } `json:"data"`
  }
  if err := json.NewDecoder(resp.Body).Decode(&fileUploadData); err != nil {
    fmt.Println("Error decoding file upload response:", err)
    return
  }

  fileURL := fileUploadData.Data.Attributes.URL
  fileURLSignature := fileUploadData.Data.Attributes.URLSignature

  // Step 2: PUT file to the signed URL
  file, err := os.Open("path_to_your_file.pdf")
  if err != nil {
    fmt.Println("Error opening file:", err)
    return
  }
  defer file.Close()

  req, err = http.NewRequest("PUT", fileURL, file)
  if err != nil {
    fmt.Println("Error creating PUT request:", err)
    return
  }

  resp, err = client.Do(req)
  if err != nil {
    fmt.Println("Error sending PUT request:", err)
    return
  }
  defer resp.Body.Close()

  if resp.StatusCode != http.StatusOK {
    fmt.Printf("Failed to upload the file, status: %d\n", resp.StatusCode)
    return
  }

  // Step 3: POST letter details to the API
  payload := map[string]interface{}{
    "data": map[string]interface{}{
      "type": "letters",
      "attributes": map[string]interface{}{
        "file_original_name": "your_filename.pdf",
        "file_url": fileURL,
        "file_url_signature": fileURLSignature,
        "address_position": "left",
        "auto_send": false,
      },
    },
  }
  payloadBytes, err := json.Marshal(payload)
  if err != nil {
    fmt.Println("Error marshalling payload:", err)
    return
  }

  req, err = http.NewRequest("POST", urlLetters, bytes.NewBuffer(payloadBytes))
  if err != nil {
    fmt.Println("Error creating POST request:", err)
    return
  }
  req.Header.Set("Content-Type", "application/vnd.api+json")
  req.Header.Set("Authorization", "Bearer "+accessToken)

  resp, err = client.Do(req)
  if err != nil {
    fmt.Println("Error sending POST request:", err)
    return
  }
  defer resp.Body.Close()

  if resp.StatusCode == http.StatusCreated {
    fmt.Println("Letter successfully created!")
  } else {
    fmt.Printf("Failed to create the letter, status: %d\n", resp.StatusCode)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import (java.io.*; java.net.HttpURLConnection; java.net.URL;)
import org.json.JSONObject;

public class UploadAndCreateLetter {
  public static void main(String[] args) {
    String urlFileUpload = "https://api.pingen.com/file-upload";
    String urlLetters = "https://api.pingen.com/organisations/YOUR_ORGANISATION_UUID/letters";
    String accessToken = "INSERT_YOUR_ACCESS_TOKEN_HERE";
    String filePath = "path_to_your_file.pdf";
    String fileName = "your_filename.pdf";

    try {
      // Step 1: Get upload URL
      URL url = new URL(urlFileUpload);
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("GET");
      connection.setRequestProperty("Authorization", "Bearer " + accessToken);

      int statusCode = connection.getResponseCode();
      if (statusCode != HttpURLConnection.HTTP_OK) {
        System.out.printf("Failed to get file upload URL. HTTP Status Code: %d%n", statusCode);
        return;
      }

      StringBuilder response = new StringBuilder();
      try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
        String line;
        while ((line = br.readLine()) != null) {
          response.append(line);
        }
      }

      JSONObject data = new JSONObject(response.toString())
        .getJSONObject("data")
        .getJSONObject("attributes");
      String fileUrl = data.getString("url");
      String fileUrlSignature = data.getString("url_signature");

      connection.disconnect();

      // Step 2: Upload file
      uploadFile(fileUrl, filePath);

      // Step 3: Create letter
      createLetter(urlLetters, accessToken, fileName, fileUrl, fileUrlSignature);

    } catch (Exception e) {
      System.err.println("Error occurred: " + e.getMessage());
      e.printStackTrace();
    }
  }

  private static void uploadFile(String fileUrl, String filePath) throws IOException {
    File file = new File(filePath);
    if (!file.exists()) {
      System.err.println("File not found: " + filePath);
      return;
    }

    URL uploadUrl = new URL(fileUrl);
    HttpURLConnection connection = (HttpURLConnection) uploadUrl.openConnection();
    connection.setRequestMethod("PUT");
    connection.setDoOutput(true);

    try (OutputStream os = connection.getOutputStream();
      FileInputStream fis = new FileInputStream(file)) {
      byte[] buffer = new byte[1024];
      int bytesRead;
      while ((bytesRead = fis.read(buffer)) != -1) {
        os.write(buffer, 0, bytesRead);
      }
    }

    int uploadStatusCode = connection.getResponseCode();
    if (uploadStatusCode != HttpURLConnection.HTTP_OK && uploadStatusCode != HttpURLConnection.HTTP_CREATED) {
      System.out.printf("File upload failed. HTTP Status Code: %d%n", uploadStatusCode);
    } else {
      System.out.println("File uploaded successfully.");
    }

    connection.disconnect();
  }

  private static void createLetter(String urlLetters, String accessToken, String fileName, String fileUrl,
    String fileUrlSignature) throws IOException {
    URL url = new URL(urlLetters);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("POST");
    connection.setRequestProperty("Content-Type", "application/vnd.api+json");
    connection.setRequestProperty("Authorization", "Bearer " + accessToken);
    connection.setDoOutput(true);

    JSONObject payload = new JSONObject();
    JSONObject data = new JSONObject();
    JSONObject attributes = new JSONObject();

    attributes.put("file_original_name", fileName);
    attributes.put("file_url", fileUrl);
    attributes.put("file_url_signature", fileUrlSignature);
    attributes.put("address_position", "left");
    attributes.put("auto_send", false);

    data.put("type", "letters");
    data.put("attributes", attributes);
    payload.put("data", data);

    try (OutputStream os = connection.getOutputStream()) {
      os.write(payload.toString().getBytes());
    }

    int statusCode = connection.getResponseCode();
    if (statusCode == HttpURLConnection.HTTP_CREATED) {
      System.out.println("Letter created successfully.");
    } else {
      System.out.printf("Failed to create letter. HTTP Status Code: %d%n", statusCode);
    }

    connection.disconnect();
  }
}
Graem Lourens, CTO van Pingen

“We maken het ontwikkelaars graag makkelijk – niet alleen bij de integratie, maar ook op de lange termijn. Een tevreden ontwikkelaar is onze beste verkoopstrategie. Met onze API verstuur je je eerste brief in slechts 5 minuten. Zo simpel is het.”

Graem Lourens, medeoprichter en CTO van Pingen

Gebruiksklare componenten

Voorgeconfigureerde modules zorgen voor een snelle setup.

Eenvoudige integratie

Intuïtieve WebApp voor een naadloze API-verbinding.

Consistente updates

Garandeert compatibiliteit met evoluerende platforms.

Tijd- en kostenbesparingen

Minimaliseer ontwikkelings- en onderhoudsinspanningen.

Meerdere programmeertalen

Vanuit ons beschikbaar voor PHP, Python en .Net.

Duidelijke documentatie

Duidelijke handleidingen voor snelle implementatie.

Krachtige SDK's

Onze SDK's zijn ontworpen om de API-integratie te vereenvoudigen, kosten en tijd te besparen, en tegelijkertijd een soepele en betrouwbare ervaring te bieden op verschillende platforms en in meerdere talen.

Bekijk onze SDK's

Real-time updates via webhooks

Pingen biedt automatische webhookmeldingen, met realtime updates over de status van brieven. Je ontvangt direct meldingen voor verzonden brieven, problemen of onbestelbare items, zodat je snel kunt reageren zonder actief de Pingen API te monitoren.

Webhooks-voorbeelden
Pingen-webhooksdashboard met details van een onbestelbare postgebeurtenis, JSON-payload en successtatus

Stagingomgeving voor developers

Pingen biedt een stagingomgeving die het productiesysteem exact nabootst, maar volledig gescheiden is. Zo kun je alles kostenloos en zonder risico’s testen voordat je live gaat.

Testen zonder risico

Gebruik onze staging om integraties veilig te testen zonder live data te beïnvloeden of kosten te maken.

Illustratie van de staging-omgeving

Volledige functie-simulatie

Pingen's staging bootst alle functies na, zodat je je werkprocessen veilig kunt testen, van het verzenden tot het volgen van brieven.

Debug voor livegang

Identificeer en los problemen op in een gecontroleerde omgeving voordat je live gaat, waardoor fouten in de productie worden vermeden.

Ontwikkelaarsvriendelijk

Onze sandbox is ontworpen voor ontwikkelaars om integratietests te vereenvoudigen en de ontwikkeling te versnellen.

Aan de slag

1

Meld je gratis aan

Maak een gratis account aan om aan de slag te gaan met Pingen en toegang te krijgen tot onze WebApp en de brief API.

2

Verkrijg je API-key

Maak een Developer App in Pingen aan om de Client-ID en Client-Secret te ontvangen die nodig zijn voor API-authenticatie.

3

Integreer de API

Gebruik een van de SDK's of maak je eigen integratie op basis van onze API-documentatie en CURL-voorbeelden.

4

Test en ga live

Test je integratie in onze stagingomgeving en volg de gebeurtenissen via de WebApp en webhookmeldingen.