Options
All
  • Public
  • Public/Protected
  • All
Menu

Ideal Postcodes Core Interface

JavaScript API for api.ideal-postcodes.co.uk

CircleCI Coverage Status Dependency Status BrowserStack Status npm version npm bundle size (scoped) npm bundle size (scoped) install size

@ideal-postcodes/core-interface is an environment agnostic implementation of the Ideal Postcodes JavaScript API client interface.

If you are looking for the browser or Node.js client which implements this interface, please check out the downstream clients links.

Links

Downstream Clients

Documentation

Methods

Usage

To install, pick one of the following based on your platform

# For browser client
npm install @ideal-postcodes/core-browser

# For node.js client
npm install @ideal-postcodes/core-node

# For generic interface (you need to supply your own HTTP agent)
npm install @ideal-postcodes/core-interface

Instantiate a client with

import { Client } from "@ideal-postcodes/core-<package-type>";

const client = new Client({ api_key: "iddqd" });

// Only api_key is required by core-node and core-browser - all others are optional
// The agentless interface requires explicit configuration

Configuration options


Quick Methods

The client exposes a number of simple methods to get at the most common tasks when interacting with the API

Lookup a Postcode

Return addresses associated with a given postcode

const postcode = "id11qd";

client.lookupPostcode({ postcode }).then(addresses => {
  console.log(addresses);
  {
    postcode: "ID1 1QD",
    line_1: "2 Barons Court Road",
    // ...etc...
  }
});

Method options

Search for an Address

Return addresses associated with a given query

const query = "10 downing street sw1a";

client.lookupAddress({ query }).then(addresses => {
  console.log(addresses);
  {
    postcode: "SW1A 2AA",
    line_1: "Prime Minister & First Lord Of The Treasury",
    // ...etc...
  }
});

Method options

Search for an Address by UDPRN

Return address for a given udprn

Invalid UDPRN will return null

const udprn = 23747771;

client.lookupUdprn({ udprn }).then(address => {
  console.log(address);
  {
    postcode: "SW1A 2AA",
    line_1: "Prime Minister & First Lord Of The Treasury",
    // ...etc...
  }
});

Method options

Search for an Address by UMPRN

Return address for a given umprn

Invalid UMPRN will return null

const umprn = 50906066;

client.lookupUmprn({ umprn }).then(address => {
  console.log(address);
  {
    postcode: "CV4 7AL",
    line_1: "Room 1, Block 1 Arthur Vick",
    // ...etc...
  }
});

Method options

Check Key Usability

Check if a key is currently usable

client.checkKeyUsability({}).then(key => {
  console.log(key.available); // => true
});

Method options


Resources

Resources defined in the API documentation are exposed on the client. Each resource exposes a method (#retrieve, #list, etc) which maps to a resource action.

These methods expose a low level interface to execute HTTP requests and observe HTTP responses. They are ideal if you have a more complex query or usecase where low level access would be useful.

Resource methods return a promise with a HTTP response object type.

Retrieve

Requesting a resource by ID (e.g. a postcode lookup for postcode with ID "SW1A 2AA") maps to the #retrieve method.

The first argument is the resource ID. The second argument is an object which accepts header and query attributes that map to HTTP header and the request querystring.

client.resourceName.retrieve("id", {
  query: {
    api_key: "foo",
    tags: "this,that,those",
    licensee: "sk_99dj3",
  },
  header: {
    "IDPC-Source-IP": "8.8.8.8",
  },
  timeout: 5000,
});

List

Requesting a resource endpoint (e.g. an address query to /addresses) maps to the #list method.

client.resourceName.list({
  query: {
    api_key: "foo",
    query: "10 downing street"
  },
  header: {
    "IDPC-Source-IP": "8.8.8.8",
  },
  timeout: 5000,
});

The first and only argument is an object which accepts header and query attributes that map to HTTP header and the request querystring.

Custom Actions

Some endpoints are defined as custom actions, e.g. /keys/:key/usage. These can be invoked using the name of the custom action.

E.g. for key usage data extraction

client.keys.usage(api_key, {
  query: {
    tags: "checkout,production"
  },
  header: {
    Authorization: 'IDEALPOSTCODES user_token="foo"',
  },
  timeout: 5000,
});

Resource Methods

Listed below are the available resources exposed by the client:

Postcodes

Retrieve addresses for a postcode.

client.postcodes.retrieve("SW1A2AA", {
  header: {
    "Authorization": 'IDEALPOSTCODES api_key="iddqd"',
  },
}).then(response => {
  const addresses = response.body.result;
}).catch(error => logger(error));

See postcode resource API documentation

Addresses

Search for an address

client.addresses.list({
  query: {
    query: "10 Downing street",
  },
  header: {
    "Authorization": 'IDEALPOSTCODES api_key="iddqd"',
  },
}).then(response => {
  const addresses = response.body.result.hits;
}).catch(error => logger(error));

See addresses resource API documentation

Autocomplete

Autocomplete an address given an address partial

client.autocomplete.list({
  query: {
    query: "10 Downing stre",
  },
  header: {
    "Authorization": 'IDEALPOSTCODES api_key="iddqd"',
  },
}).then(response => {
  const suggestions = response.body.result.hits;
}).catch(error => logger(error));

See autocomplete resource API documentation

UDPRN

Retrieve an address given a UDPRN

client.udprn.retrieve("12345678", {
  header: {
    "Authorization": 'IDEALPOSTCODES api_key="iddqd"',
  },
}).then(response => {
  const address = response.body.result;
}).catch(error => logger(error));

See UDPRN resource API documentation

UMPRN

Retrieve a multiple residence premise given a UMPRN

client.umprn.retrieve("87654321", {
  header: {
    "Authorization": 'IDEALPOSTCODES api_key="iddqd"',
  },
}).then(response => {
  const address = response.body.result;
}).catch(error => logger(error));

See UMPRN resource API documentation

Keys

Find out if a key is available

client.keys.retrieve("iddqd", {})
  .then(response => {
    const { available } = response.body.result;
  }).catch(error => logger(error));

Get private information on key (requires user_token)

client.keys.retrieve("iddqd", {
  header: {
    "Authorization": 'IDEALPOSTCODES user_token="secret-token"',
  },
}).then(response => {
  const key = response.body.result;
}).catch(error => logger(error));

Get key usage data

client.keys.usage("iddqd", {
  header: {
    "Authorization": 'IDEALPOSTCODES user_token="secret-token"',
  },
}).then(response => {
  const key = response.body.result;
}).catch(error => logger(error));

See Keys resource API documentation


Error Handling

Client exports a static variable errors which contains custom error constructors that wrap specific API errors. These constructors can be used to test for specific cases using the instanceof operator.

For example:

const { IdpcInvalidKeyError } = Client.errors;

try {
  const addresses = client.lookupPostcode({ postcode: "SW1A2AA" });
} catch (error) {
  if (error instanceof IdpcInvalidKeyError) {
    // Handle an invalid key error
  }
}

Not all specific API errors will be caught. If a specific API error does not have an error constructor defined, a more generic error (determined by the HTTP status code) will be returned.

For example:

const { IdpcRequestFailedError } = Client.errors;

try {
  const addresses = client.lookupPostcode({ postcode: "SW1A2AA" });
} catch (error) {
  if (error instanceof IdpcRequestFailedError) {
    // IdpcRequestFailedError indicates a 402 response code
    // Possibly the key balance has been depleted
  }
}

A sketch of the error prototype chain can be found here


Core Interface Errors

For more advanced use cases, this core-interface library provides:

  • Class implementations for Ideal Postcodes API errors that inherit from Error
  • A parser that converts raw error data into one of these error instances

Usage

Aside from inspecting the HTTP request status code and/or JSON body response codes, you may also test for specific error instances.

Errors that don't inherit from IdealPostcodesError would indicate some kind of error external to the API (e.g. bad network, request timeout).

import { errors } from "@ideal-postcodes/core-interface";
const { IdpcPostcodeNotFoundError } = errors;

// Handle a specific error
if (error instanceof IdpcPostcodeNotFoundError) {
  // You got yourself an invalid API Key
}

// Alternatively use a switch statement
switch (true) {
  case error instanceof IdpcPostcodeNotFoundError:
    // You got yourself an invalid API Key
  default:
    // Default error handling path
}

Error Prototype Chain

All errors inherit from JavaScript's Error prototype.

Errors are grouped by HTTP status code classes.

Specific errors may be supplied for the following reasons:

  • Convenience: They are frequently tested for (e.g. invalid postcode, postcode not found)
  • Developer QoL. They are useful for debug purposes during the implementation stages
Prototype Chain

# Parent class inherits from Javascript Error. Returned if no JSON Response body
IdealPostcodesError < Error
|
|- IdpcApiError # Generic Error Class, returned if JSON response body present
   |
   |- IdpcBadRequestError          # 400 Errors
   |- IdpcUnauthorisedError        # 401 Errors
   |- IdpcRequestFailedError       # 402 Errors
   |  |- IdpcBalanceDepletedError
   |  |- IdpcLimitReachedError
   |
   |- IdpcResourceNotFoundError    # 404 Errors
   |  |- IdpcPostcodeNotFoundError
   |  |- IdpcKeyNotFoundError
   |  |- IdpcUdprnNotFoundError
   |  |- IdpcUmprnNotFoundError
   |
   |- IdpcServerError              # 500 Errors

Error Parser

The error parser consumes a HTTP API response and returns the correct error instance.

import { errors } from "@ideal-postcodes/core-interface";
const { parse, IdpcPostcodeNotFoundError } = errors;

const invalidPostcodeUrl = "https://api.ideal-postcodes.co.uk/v1/postcodes/bad_postcode?api_key=iddqd"

const response = await fetch(invalidPostcodeUrl);

// Generate an error object if present, otherwise returns `undefined`
const error = parse(response);

// Handle the error
if (error instanceof IdpcPostcodeNotFoundError) {...}

Test

npm test

Licence

MIT

Index

Classes

Interfaces

Type aliases

Variables

Functions

Type aliases

AddressKeys

AddressKeys: keyof Address

AuthenticationOptions

AuthenticationOptions: Partial<Authenticable & AdminAuthenticable>

Credentials

Credentials: [string, string][]

Header

Header: StringMap

Header

Optional Authorization

Authorization: undefined | string

Optional IDPC-Source-IP

IDPC-Source-IP: undefined | string

HttpVerb

HttpVerb: "GET" | "POST" | "DELETE" | "PUT" | "PATCH" | "DELETE"

KeyResponse

KeyResponse: PublicKeyResponse | PrivateKeyResponse

Protocol

Protocol: "http" | "https"

Query

Query: StringMap

Query

Optional api_key

api_key: undefined | string

Optional box

box: undefined | string

Optional building_name

building_name: undefined | string

Optional building_number

building_number: undefined | string

Optional country

country: undefined | string

Optional dependant_locality

dependant_locality: undefined | string

Optional dependant_thoroughfare

dependant_thoroughfare: undefined | string

Optional district

district: undefined | string

Optional filter

filter: undefined | string

Optional licensee

licensee: undefined | string

Optional limit

limit: undefined | string

Optional organisation_name

organisation_name: undefined | string

Optional page

page: undefined | string

Optional post_town

post_town: undefined | string

Optional postcode

postcode: undefined | string

Optional postcode_outward

postcode_outward: undefined | string

Optional postcode_type

postcode_type: undefined | string

Optional su_organisation_indicator

su_organisation_indicator: undefined | string

Optional sub_building_name

sub_building_name: undefined | string

Optional tags

tags: undefined | string

Optional thoroughfare

thoroughfare: undefined | string

Optional ward

ward: undefined | string

Variables

Const API_URL

API_URL: "api.ideal-postcodes.co.uk" = "api.ideal-postcodes.co.uk"

Default API endpoint

Const BAD_REQUEST

BAD_REQUEST: 400 = 400

Const BALANCE_DEPLETED

BALANCE_DEPLETED: 4020 = 4020

Const INVALID_KEY

INVALID_KEY: 4010 = 4010

Const KEY_NOT_FOUND

KEY_NOT_FOUND: 4042 = 4042

Const LIMIT_REACHED

LIMIT_REACHED: 4021 = 4021

Const NOT_FOUND

NOT_FOUND: 404 = 404

Const OK

OK: 200 = 200

Const PAYMENT_REQUIRED

PAYMENT_REQUIRED: 402 = 402

Const POSTCODE_NOT_FOUND

POSTCODE_NOT_FOUND: 4040 = 4040

Const REDIRECT

REDIRECT: 300 = 300

Const SERVER_ERROR

SERVER_ERROR: 500 = 500

Const STRICT_AUTHORISATION

STRICT_AUTHORISATION: false = false

Const TIMEOUT

TIMEOUT: 10000 = 10000

Default HTTP timeout in milliseconds. Defaults to 10s

Const TLS

TLS: true = true

Use TLS by default. Set to true

Const UDPRN_NOT_FOUND

UDPRN_NOT_FOUND: 4044 = 4044

Const UMPRN_NOT_FOUND

UMPRN_NOT_FOUND: 4046 = 4046

Const UNAUTHORISED

UNAUTHORISED: 401 = 401

Const VERSION

VERSION: "v1" = "v1"

Default API Version number. Defaults to "v1"

Const resource

resource: "autocomplete/addresses" = "autocomplete/addresses"

Functions

Const appendAuthorization

  • appendAuthorization(__namedParameters: object): StringMap
  • appendAuthorization

    Mutates a headers object to include Authorization header. Will insert if found:

    • api_key
    • licensee
    • user_token

    Parameters

    • __namedParameters: object

    Returns StringMap

Const appendFilter

  • appendFilter(__namedParameters: object): StringMap

Const appendIp

  • appendIp(__namedParameters: object): StringMap

Const appendPage

  • appendPage(__namedParameters: object): StringMap

Const appendTags

  • appendTags(__namedParameters: object): StringMap

Const create

Const isErrorResponse

  • isErrorResponse(body: unknown): boolean
  • Parameters

    • body: unknown

    Returns boolean

Const isNumber

  • isNumber(n: any): boolean
  • Parameters

    • n: any

    Returns boolean

Const isObject

  • isObject(o: unknown): boolean
  • Parameters

    • o: unknown

    Returns boolean

Const isString

  • isString(i: any): boolean
  • Parameters

    • i: any

    Returns boolean

Const isSuccess

  • isSuccess(code: number): boolean
  • Parameters

    • code: number

    Returns boolean

Const listMethod

  • listMethod<T, U>(options: Options): (Anonymous function)
  • Type parameters

    Parameters

    Returns (Anonymous function)

Const parse

  • parse

    Parses API responses and returns an error for non 2xx responses

    Upon detecting an error an instance of IdealPostcodesError is returned

    Parameters

    Returns Error | void

Const retrieveMethod

  • retrieveMethod<T, U>(options: Options): (Anonymous function)
  • Type parameters

    Parameters

    Returns (Anonymous function)

Const toAuthHeader

  • toAuthHeader

    Extracts credentials into authorization header format

    Parameters

    Returns string

Const toCredentialString

  • Parameters

    Returns string

Const toHeader

  • toHeader(__namedParameters: object, client: Client): Header
  • toHeader

    Extracts HTTP Header object from request and client default headers

    Precendence is given to request specific headers

    Parameters

    Returns Header

Const toRetrieveUrl

  • toRetrieveUrl(options: Options, id: string): string
  • Parameters

    Returns string

Const toStringMap

  • toQuery

    Shallow copies object while omitting undefined attributes

    Parameters

    Returns StringMap

Const toTimeout

  • toTimeout(__namedParameters: object, client: Client): number
  • toTimeout

    Returns timeout value from request object. Delegates to default client timeout if not specified

    Parameters

    • __namedParameters: object
      • timeout: undefined | number
    • client: Client

    Returns number