REST-Jdbc — Webmetic

Webmetic identifies B2B website visitors and exposes company data via a REST API. This example reads company master data from /company (wem_company) with rows under result and page pagination (page, page_size).

Quick start with the JDBC client

java -jar /path/to/restjdbc.jar webmetic.sql

The file webmetic.sql contains the connection and sample queries. Steps:

  1. Obtain the driver JAR (absolute path to restjdbc.jar)
  2. Copy the API key from the Webmetic dashboard under API
  3. Replace apiKey=XXXX in webmetic.sql with your API key
  4. Run the command in the folder that contains webmetic.sql and webmetic-spec.json
connect 'jdbc:rest:https://hub.webmetic.de|spec=webmetic-spec.json,auth=apikey,apiKey=Your_API_key,apiKeyLocation=header,apiKeyParam=Authorization,requestIntervalMs=1000'

1. JDBC URL

jdbc:rest:https://hub.webmetic.de

The API base URL is set in the JDBC URL.

Component Value
Driver prefix jdbc:rest:
API base URL https://hub.webmetic.de
Schema (SQL) public (default)

Sample connection (Java):

Properties props = new Properties();
props.setProperty("spec", "/path/to/webmetic-spec.json");
props.setProperty("auth", "apikey");
props.setProperty("apiKey", System.getenv("WEBMETIC_API_KEY"));
props.setProperty("apiKeyLocation", "header");
props.setProperty("apiKeyParam", "Authorization");
props.setProperty("requestIntervalMs", "1000");

Connection conn = DriverManager.getConnection(
    "jdbc:rest:https://hub.webmetic.de", props);

2. Connection properties

Property Value for Webmetic Required
spec Path to spec (see below) Yes
auth apikey Yes
apiKey API key from the Webmetic dashboard Yes
apiKeyLocation header Yes
apiKeyParam Authorization Yes
requestIntervalMs Minimum milliseconds between HTTP requests (1000 for Webmetic) Recommended
retryOn429 Automatically retry on HTTP 429 (default: true) No
maxRetries Maximum retries on HTTP 429 (default: 5) No
stdoutlog Debug output: cursor, http, rows, or all (e.g. cursor+http+rows) No

Minimal:

props.setProperty("spec", "/path/to/webmetic-spec.json");
props.setProperty("auth", "apikey");
props.setProperty("apiKey", "Your_API_key");
props.setProperty("apiKeyLocation", "header");
props.setProperty("apiKeyParam", "Authorization");
props.setProperty("requestIntervalMs", "1000");

Property names are case-insensitive (e.g. apikey, apikeylocation, and apikeyparam also work).

Spec path: absolute path to your local copy of the spec file.

Spec file: webmetic-spec.json

3. Spec file

File: webmetic-spec.json

Column names and data types in the spec follow the target table analysis.trs_wem_company:

CREATE TABLE analysis.trs_wem_company (
   company_id VARCHAR(255) NOT NULL
 , company_name VARCHAR(500)
 , address VARCHAR(1000)
 , postal_code VARCHAR(255)
 , city VARCHAR(255)
 , country VARCHAR(8000)
 , country_code VARCHAR(8000)
 , directors VARCHAR(8000)
 , phone_number VARCHAR(255)
 , fax_number VARCHAR(255)
 , email_address VARCHAR(255)
 , email_pattern VARCHAR(50)
 , email_pattern_confidence DECIMAL(15,6)
 , vat_id VARCHAR(255)
 , tax_number VARCHAR(255)
 , registration_number VARCHAR(1000)
 , registration_court VARCHAR(255)
 , company_url VARCHAR(255)
 , company_logo_url VARCHAR(255)
 , primary_color VARCHAR(50)
 , secondary_color VARCHAR(50)
 , linkedin VARCHAR(255)
 , facebook VARCHAR(255)
 , instagram VARCHAR(255)
 , youtube VARCHAR(255)
 , twitter VARCHAR(255)
 , organization_type VARCHAR(255)
 , short_description_en VARCHAR(1000)
 , short_description_de VARCHAR(1000)
 , full_description_en VARCHAR(5000)
 , full_description_de VARCHAR(5000)
 , what_they_do_de VARCHAR(5000)
 , what_they_do_en VARCHAR(5000)
 , how_they_make_money_de VARCHAR(5000)
 , how_they_make_money_en VARCHAR(5000)
 , target_audience_de VARCHAR(5000)
 , target_audience_en VARCHAR(5000)
 , employee_count VARCHAR(255)
 , revenue VARCHAR(255)
);

The spec maps the same column names and SQL-like types (VARCHAR(n), DECIMAL(p,s)) to the REST entity wem_company. Full file: webmetic-spec.json.

Excerpt:

{
  "entities": [
    {
      "name": "wem_company",
      "path": "/company",
      "dataPath": "/result",
      "write": false,
      "columns": [
        { "name": "company_id", "type": "VARCHAR(255)", "primaryKey": true },
        { "name": "company_name", "type": "VARCHAR(500)" },
        { "name": "email_pattern_confidence", "type": "DECIMAL(15,6)" }
      ],
      "pagination": {
        "type": "page",
        "pageParam": "page",
        "limitParam": "page_size",
        "defaultLimit": 10000
      }
    }
  ]
}

Table wem_company

SQL table REST path JSON rows Pagination
wem_company /company /result page with page_size / page (default: 10000 per page)

The driver sets page and page_size automatically and fetches all pages until an empty response is returned.

Adjustments: Endpoint path (path), JSON structure (dataPath), and columns must match your Webmetic API documentation. Nested objects in the API response may require jsonPath on individual columns.

4. Authentication

Webmetic provides an API key in the dashboard (section API). The API expects the key in the Authorization header without a Bearer prefix:

Authorization: Your_API_key

Use auth=apikey with the header name Authorization — not auth=bearer, which would send Authorization: Bearer …:

props.setProperty("auth", "apikey");
props.setProperty("apiKey", "Your_API_key");
props.setProperty("apiKeyLocation", "header");
props.setProperty("apiKeyParam", "Authorization");
props.setProperty("requestIntervalMs", "1000");

The driver sends: Authorization: Your_API_key

See also the main documentation.

5. Rate limits

Webmetic allows about 1 request per second. Configure throttling via connection properties:

Property Value for Webmetic
requestIntervalMs 1000
retryOn429 true (default)
maxRetries 5 (default)

The driver does not wait a fixed second after every call. It tracks the start time of the last request and waits only for the remaining time until the interval has elapsed. On HTTP 429, the request is retried automatically; the wait time comes from the Retry-After header or from requestIntervalMs.

props.setProperty("requestIntervalMs", "1000");
props.setProperty("retryOn429", "true");

See also the main documentation.

6. SQL examples

SELECT company master data

SELECT company_id, company_name, city, country, company_url, employee_count, revenue
FROM wem_company
;
SQL HTTP (simplified)
SELECT … FROM wem_company GET …/company?page_size=10000&page=1

If the API expects query parameters, combine them in FILTER with AND:

SELECT company_id, company_name, city, country
FROM wem_company
FILTER company_id='12345'
;

page and page_size come from pagination in the spec — do not put them in the FILTER clause.

Use single quotes for string values. AND is case-insensitive (and works as well).

INSERT, UPDATE, DELETE

Not supported ("write": false).

7. System tables

SELECT table_name, remarks FROM system.table_list;

SELECT column_name, type_name, column_size, decimal_digits
FROM system.column_list
WHERE table_name = 'wem_company'
;

SELECT column_name FROM system.pk_list WHERE table_name = 'wem_company';

8. Notes

  • API documentation: Verify endpoint names, auth format, and JSON structure in your Webmetic developer hub and adjust the spec if needed.
  • Rate limits: Webmetic typically allows 1 request per second. Set requestIntervalMs=1000 — the driver waits only for the remaining time since the last request, not a fixed 1 second after every call. On HTTP 429, the driver retries automatically (retryOn429, default true); wait time comes from the Retry-After header or from requestIntervalMs.
  • FILTER errors: On invalid FILTER syntax, the error message shows the received FILTER text. Use stdoutlog=cursor+http to see the FILTER and the generated HTTP URL.
  • More endpoints: Webmetic also offers /company-sessions, /intensive-visits, /new-visits, and /returning-visits — add them as further entities in the same spec.
  • Nested fields: If the API returns nested objects (e.g. structured address data), map them with jsonPath in the spec.