# Bulk add IP labels (php)

{% stepper %}
{% step %}

### Update credential variables

Update the following variables (located at the top of the file) accordingly:

`USERNAME`\
`PASSWORD`\
`IPLABEL_PAYLOAD`

```php
<?php
  # Copyright (c) 2022 Netography, Inc. All rights reserved.

  # A PHP script to upload multiple IP Address labels
  # Usage: $ php neto-bulk-add-ip-labels.php

  # ~~ BEGIN Configuration ~~~ #

  # Authentication Credentials used to login to the Netography Portal
  # Note: it is recommended to create a new user specifically for API and integration purposes
  $USERNAME = 'Username';
  $PASSWORD = 'Password';

  # API Endpoints & Data
  $API_BASE_URL = 'https://api-develop.netography.com/api';
  $ACCESS_TOKEN_URL = $API_BASE_URL . '/auth/bearer/token';
  $IPLABEL_URL = $API_BASE_URL . '/v1/labels/ips/bulk-upload?overwrite=true';

  $IPLABEL_PAYLOAD = array(
    array(
      'ip' => '12.1.0.100',
      // 'context' => 'name', // name is the default context, and not required.
      'labels' => [ 'label name' ]
    ),
    array(
      'ip' => '12.1.0.101',
      'context' => 'beer',
      'labels' => [ 'Bug Light', 'Coors Light', 'Corona Extra' ]
    ),
  );

  // path/filename to cache the JWT auth token 
  $CACHE_FILE = '/tmp/neto-apiat';

  # ~~ END Configuration ~~~ #
  
  if (empty($USERNAME) || 'CHANGEME' == $USERNAME) {
    exit("USERNAME variable is required to be configured.\n");
  }
  
  if (empty($PASSWORD) || 'CHANGEME' == $USERNAME) {
    exit("PASSWORD variable is required to be configured.\n");
  }

  # Cache token and re-use if not expired
  $jwt_valid = false;
  $access_token = null;
  if (file_exists($CACHE_FILE)) {
    $cache_data = file_get_contents($CACHE_FILE);
    $cache_json = json_decode($cache_data);
    $access_token = $cache_json->{'access_token'};
    $expires_in = $cache_json->{'expires_in'};
    $token_date = filemtime($CACHE_FILE);
    $expire_timestamp = $token_date + $expires_in - 60; // account for some clock skew
    // echo 'JWT expires at ' . date('Y-m-d H:i:s', $expire_timestamp) . "\n";

    if (time() <= $expire_timestamp) {
      $jwt_valid = true;
    }
  }

  if (!$jwt_valid) {
    $postvars = http_build_query(array(
      'username' => $USERNAME,
      'password' => $PASSWORD
    ));

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $ACCESS_TOKEN_URL);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close ($ch);

    $jwt = json_decode($response);
    $access_token = $jwt->{'access_token'};
    // echo $access_token;

    file_put_contents($CACHE_FILE, $response);

  }

  $json_payload = json_encode($IPLABEL_PAYLOAD);

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $IPLABEL_URL);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($json_payload),
    'Authorization: Bearer ' . $access_token)
  );
  curl_setopt($ch, CURLOPT_POSTFIELDS, $json_payload);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $response = curl_exec($ch);

  echo $response;
  echo "\n";
  exit();


?>
```

{% endstep %}
{% endstepper %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fusion.vectra.ai/api-recipes/recipes/bulk-add-ip-labels-php.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
