WQX Web API - 9/28/2018

WQX Web Application Programming Interface (API)

Introduction

EPA’s Water Quality eXchange team, the Chesapeake Bay Program, and EPA Contractor Gold Systems have developed, tested, and utilized a new way to submit data to WQX and the Water Quality Portal. Until very recently the only two methods to publish your data via WQX were to set up an automated node to node communication via EPA’s Exchange Network or to manually upload your data using the WQX Web user interface. The Chesapeake Bay Program recently began publishing their data using automated API services through WQX Web. The new WQX Web API services allow a data submitter to automate data submissions like a node but through WQX Web. The API is intended to provide programmatic access to WQX Web data submission functions and procedures. The intended audience is programmers who are familiar with the concepts and techniques of WQX data submissions and Web Services. This project is innovative because maintenance on the data mapping is managed within the WQX Web. The interface makes maintaining data translation rules easy and user friendly. WQX Web maintains compatibility with new business rules, elements and xml schema validation.hing their data using automated API services through WQX Web. 

Access to the WQX Web API

The API is available to registered users within the WQX Web application. Before using the API, users must obtain a unique 88-character “Private Encryption Key”: associated with a registered WQX Web user account. Developers / programmers may initial use their private and personal account. Later for releasing production applications one may email a request to register an application (WQX Web user) account

All API access is through an authenticated Uniform Resource Identifier (URI). Data is submitted by sending an HTTP GET/POST to the URI with appropriate parameters supplied. The minimum parameters for every request include the UserID, Timestamp, and Signature, which includes the name of the method being invoked.

Where to find the “Private Encryption Key”: (WQX Web)

Click “Setup” Menu,

Click “My User Account Details” menu item
 

Home Page

Setup

Domain Values

Import & Submit

Review

Administrator

Help

User Details

Return

Save

Cancel

User Access Rights

Preferences

Status:

 

Login Name:

 

Full Name:

 

Role:

 

WQX/NAAS ID:

 

Affiliation:

 

Address:

 

City:

 

State:

 

Zip:

 

Country:

 

Phone #:

 

Email:

 

Private Encryption Key:

Create New Key

Last Login Date:

 

 

 

Create ID

Create a Private encryption key for calling Web Services?

OK

Cancel

 

  1. DEVELOPERS and PROGRAMMERS click           <<OK>>
  2. Graphical User Interface or App Users click             <<Cancel>>

 

Program Language

The API may be used with any language capable of issuing HTTPS requests with an HMAC-SHA256 encryption algorithm (Java, PHP, Perl, Python, C, etc.

Data Return Format

The API returns data in format(s): JSON, XML.

Documentation for the WQX Web API services can be referenced via WQX Web Help Menus. Example Code is also available via both WQX Web Help Menu and STORET FTP Site URL: ftp://newftp.epa.gov/storet/wqx/api/Example_code.txt

WQX Web API Described below are the RESTful web services for WQX Web. These services are designed and used to submit water quality data to WQX. The basic process flow is as follows:
1. Upload a file and optional attachment.
2. Request that WQX Web start importing the uploaded file. There are up to five for overriding generated element/value parameter combinations. These parameters can be used to alter any existing generated elements in the import configuration.
3. Get the status for that dataset, periodically, to confirm whether it imported without any errors
4. If the final status is "Imported", then ask WQX Web to submit that dataset to CDX. During that process, the data from your flat file or spreadsheet will be converted to XML (via an import configuration that you previously created) and submitted to CDX. Alternatively, you can request that WQX Web automatically export and submit your dataset to CDX upon completion of the import. It's important to understand that data is not final/permanent until it has been submitted to CDX and has received a final status of "Completed at CDX"
5. If a dataset receives a status of Failed, you can get a list of documents relating to the dataset, and download the "Import Log.xlsx" or "ProcessingReport.zip" (among other files) to review the issues with your import file or the submission to CDX.

At end of this document, you will find an example of how to upload a file and check the status of a dataset.

 

 

RESTful Web Service Methods:

 

 

Each web service call will include a header with the following items:

  1. X-UserID
  2. X-Stamp
  3. X-Signature

The following example demonstrates how to call a web service with the required header information.



This example uses C#, but you can use any language that provides an HMAC-SHA256 encryption algorithm:


 


 

  using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Net;


namespace WebServiceConsole {

 
class Program {
 
static void Main (string[] args) {
// This user id and private encryption key are for illustration purposes only.
string userID = "wqxweb_userid";
string privateKey = "zHPJBAZbMaPOIVqmz1afDRW0HhovKuExPlvKsg8SIdIXCYeoHeI/bQaG0HBahYTCaGno5EljBJmzd5AKjfHC2w==";
string timeStamp = "";
string data = "";
string fileId = "";
byte[] signature;
Uri uri;
 
using (WebClient client = new WebClient()) {
try {
//****************************UPLOAD A FILE************************
// The URI of the upload webservice with parameters
uri = new Uri("https://cdx.epa.gov/WQXWeb/api/Upload/Projects.xlsx");
client.Headers.Add("X-UserID", userID);
timeStamp = DateTime.UtcNow.ToString();
client.Headers.Add("X-Stamp", timeStamp);
// The encrypted data must be in this order and format
data = String.Format("{0}{1}{2}{3}", userID, timeStamp, uri.ToString(), "POST");
signature = Encoding.UTF8.GetBytes(data);
using (HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(privateKey))) {
byte[] signatureBytes = hmac.ComputeHash(signature);
client.Headers.Add("X-Signature", Convert.ToBase64String(signatureBytes));
}
// Decide what type of content to be returned (text/plain, json, xml)
client.Headers.Add("Content-Type", "text/plain");
FileStream sourceFile = new FileStream("c:\users\user\Documents\ImportFile\Projects.xlsx", FileMode.Open);
BinaryReader binReader = new BinaryReader(sourceFile);
byte[] fileInput = new byte[sourceFile.Length]; //create byte array of size file
for (i = 0; i < sourceFile.Length; i++)
fileInput[i] = binReader.ReadByte(); //read until done
sourceFile.Close(); //dispose of stream
binReader.Close(); //dispose of reader
fileInput = client.UploadData(uri, fileInput);
fileId = System.Text.Encoding.UTF8.GetString(fileInput);
fileId = fileId.Substring(1, fileId.Length - 2);
 
//****************************GET STATUS OF DATASET************************
client.Headers.Clear();
// The URI of the get dataset status webservice with parameters
uri = new Uri("https://cdx.epa.gov/WQXWeb/api/GetStatus?datasetId=12345");
client.Headers.Add("X-UserID", userID);
string timeStamp = DateTime.UtcNow.ToString();
client.Headers.Add("X-Stamp", timeStamp);
// The encrypted data must be in this order and format
string data = String.Format("{0}{1}{2}{3}", userID, timeStamp, uri.ToString(), "GET");
byte[] signature = Encoding.UTF8.GetBytes(data);
using (HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(privateKey))) {
byte[] signatureBytes = hmac.ComputeHash(signature);
client.Headers.Add("X-Signature", Convert.ToBase64String(signatureBytes, Base64FormattingOptions.None));
}
// Decide what type of content to be returned (json, xml)
client.Headers.Add("Content-Type", "application/xml");
//client.Headers.Add("Content-Type", "application/json");
// Process the response
Byte[] httpMessage = client.DownloadData(uri);
if (httpMessage.Length > 0) {
Console.WriteLine(Encoding.ASCII.GetString(httpMessage));
}
}
catch (Exception e) {
Console.WriteLine(e.Message);
Console.Read();
}
}
Console.Read();
}
}
}