Repository: newrelic/newrelic-client-go
Pull request #221 (2020-03-27 01:05:13)

Update all packages to pass full URLs
Replacement / continuation of #204 that implements passing base URLs to all REST packages.  Depends on the other PR being merged.


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1bf92a4..bea70ce 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -51,6 +51,9 @@ jobs:
     steps:
       - checkout
       - run: git fetch --tags
+      - run:
+          name: Fetch deps
+          command: make deps
       - save_cache:
           key: repo-{{ .Environment.CIRCLE_SHA1 }}
           paths:
diff --git a/build/deps.mk b/build/deps.mk
index 059b097..2db989e 100644
--- a/build/deps.mk
+++ b/build/deps.mk
@@ -22,7 +22,7 @@ deps: tools deps-only
 
 
 # Determine commands by looking into cmd/*
-TOOL_COMMANDS   ?= $(shell find ${SRCDIR}/tools -type d -depth 1)
+TOOL_COMMANDS   ?= $(shell find ${SRCDIR}/tools -depth 1 -type d)
 # Determine binary names by stripping out the dir names
 TOOL_BINS       := $(foreach tool,${TOOL_COMMANDS},$(notdir ${tool}))
 
diff --git a/internal/http/client.go b/internal/http/client.go
index e75c1ca..f9e9a0d 100644
--- a/internal/http/client.go
+++ b/internal/http/client.go
@@ -11,7 +11,6 @@ import (
 
 	retryablehttp "github.com/hashicorp/go-retryablehttp"
 
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/internal/version"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 	nrErrors "github.com/newrelic/newrelic-client-go/pkg/errors"
@@ -60,14 +59,6 @@ func NewClient(cfg config.Config) Client {
 		c.Transport = http.DefaultTransport
 	}
 
-	if cfg.BaseURL == "" {
-		cfg.BaseURL = region.DefaultBaseURLs[region.Parse(string(cfg.Region))]
-	}
-
-	if cfg.NerdGraphBaseURL == "" {
-		cfg.NerdGraphBaseURL = region.NerdGraphBaseURLs[region.Parse(string(cfg.Region))]
-	}
-
 	if cfg.UserAgent == "" {
 		cfg.UserAgent = defaultUserAgent
 	}
@@ -291,11 +282,6 @@ func makeRequestBodyReader(reqBody interface{}) (*bytes.Buffer, error) {
 	return b, nil
 }
 
-// GetBaseURL returns the BaseURL used by the client
-func (c *Client) GetBaseURL() string {
-	return c.config.BaseURL
-}
-
 // Query runs a graphQL query.
 func (c *Client) Query(query string, vars map[string]interface{}, respBody interface{}) error {
 	graphqlReqBody := &graphQLRequest{
@@ -307,7 +293,7 @@ func (c *Client) Query(query string, vars map[string]interface{}, respBody inter
 		Data: respBody,
 	}
 
-	req, err := NewRequest(*c, http.MethodPost, c.config.NerdGraphBaseURL, nil, graphqlReqBody, graphqlRespBody)
+	req, err := NewRequest(*c, http.MethodPost, c.config.Region().NerdGraphURL(), nil, graphqlReqBody, graphqlRespBody)
 	if err != nil {
 		return err
 	}
diff --git a/internal/http/request.go b/internal/http/request.go
index 1ba874a..e6aaabd 100644
--- a/internal/http/request.go
+++ b/internal/http/request.go
@@ -2,7 +2,6 @@ package http
 
 import (
 	"fmt"
-	neturl "net/url"
 
 	"github.com/google/go-querystring/query"
 	retryablehttp "github.com/hashicorp/go-retryablehttp"
@@ -24,8 +23,7 @@ type Request struct {
 
 // NewRequest creates a new Request struct.
 func NewRequest(c Client, method string, url string, params interface{}, reqBody interface{}, value interface{}) (*Request, error) {
-	// Make a copy of the client's config
-	cfg := c.config
+	var err error
 
 	req := &Request{
 		method:       method,
@@ -36,14 +34,11 @@ func NewRequest(c Client, method string, url string, params interface{}, reqBody
 		authStrategy: c.authStrategy,
 	}
 
+	// FIXME: We should remove this requirement on the request
+	// Make a copy of the client's config
+	cfg := c.config
 	req.config = cfg
 
-	u, err := req.makeURL()
-	if err != nil {
-		return nil, err
-	}
-
-	var r *retryablehttp.Request
 	if reqBody != nil {
 		if _, ok := reqBody.([]byte); !ok {
 			reqBody, err = makeRequestBodyReader(reqBody)
@@ -51,19 +46,12 @@ func NewRequest(c Client, method string, url string, params interface{}, reqBody
 				return nil, err
 			}
 		}
-
-		r, err = retryablehttp.NewRequest(req.method, u.String(), reqBody)
-		if err != nil {
-			return nil, err
-		}
-	} else {
-		r, err = retryablehttp.NewRequest(req.method, u.String(), nil)
-		if err != nil {
-			return nil, err
-		}
 	}
 
-	req.request = r
+	req.request, err = retryablehttp.NewRequest(req.method, url, reqBody)
+	if err != nil {
+		return nil, err
+	}
 
 	req.SetHeader(defaultNewRelicRequestingServiceHeader, cfg.ServiceName)
 	req.SetHeader("Content-Type", "application/json")
@@ -88,26 +76,6 @@ func (r *Request) SetServiceName(serviceName string) {
 	r.SetHeader(defaultNewRelicRequestingServiceHeader, serviceName)
 }
 
-func (r *Request) makeURL() (*neturl.URL, error) {
-	u, err := neturl.Parse(r.url)
-
-	if err != nil {
-		return nil, err
-	}
-
-	if u.Host != "" {
-		return u, nil
-	}
-
-	u, err = neturl.Parse(r.config.BaseURL + u.Path)
-
-	if err != nil {
-		return nil, err
-	}
-
-	return u, err
-}
-
 func (r *Request) makeRequest() (*retryablehttp.Request, error) {
 	r.authStrategy.AuthorizeRequest(r, &r.config)
 
diff --git a/internal/region/region.go b/internal/region/region.go
deleted file mode 100644
index 45a9a8e..0000000
--- a/internal/region/region.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Package region describes the operational regions defined for New Relic
-//
-// Regions are geographical locations where the New Relic platform operates
-// and this package provides an abstraction layer for handling them within
-// the New Relic Client and underlying APIs
-package region
-
-import (
-	"strings"
-)
-
-// Region represents the members of the Region enumeration.
-type Region int
-
-const (
-	_ = iota // Ignore zero
-
-	// US represents New Relic's US-based production deployment.
-	US Region = iota
-
-	// EU represents New Relic's EU-based production deployment.
-	EU
-
-	// Staging represents New Relic's US-based staging deployment.
-	// This is for internal New Relic use only.
-	Staging
-)
-
-// Default represents the region returned if nothing was specified
-const Default Region = US
-
-// DefaultBaseURLs represents the base API URLs for the different environments of the New Relic REST API V2.
-var DefaultBaseURLs = map[Region]string{
-	US:      "https://api.newrelic.com/v2",
-	EU:      "https://api.eu.newrelic.com/v2",
-	Staging: "https://staging-api.newrelic.com/v2",
-}
-
-// NerdGraphBaseURLs describes the base URLs for the NerdGraph API.
-var NerdGraphBaseURLs = map[Region]string{
-	US:      "https://api.newrelic.com/graphql",
-	EU:      "https://api.eu.newrelic.com/graphql",
-	Staging: "https://staging-api.newrelic.com/graphql",
-}
-
-// Parse takes a Region string and returns a RegionType
-func Parse(r string) Region {
-	switch strings.ToLower(r) {
-	case "us":
-		return US
-	case "eu":
-		return EU
-	case "staging":
-		return Staging
-	default:
-		return Default
-	}
-}
-
-// String returns a human readable value for the specified Region
-func (r Region) String() string {
-	switch r {
-	case US:
-		return "US"
-	case EU:
-		return "EU"
-	case Staging:
-		return "Staging"
-	default:
-		return "(Unknown)"
-	}
-}
diff --git a/newrelic/newrelic.go b/newrelic/newrelic.go
index 048f9f7..7b62576 100644
--- a/newrelic/newrelic.go
+++ b/newrelic/newrelic.go
@@ -13,6 +13,7 @@ import (
 	"github.com/newrelic/newrelic-client-go/pkg/entities"
 	"github.com/newrelic/newrelic-client-go/pkg/nerdgraph"
 	"github.com/newrelic/newrelic-client-go/pkg/plugins"
+	"github.com/newrelic/newrelic-client-go/pkg/region"
 	"github.com/newrelic/newrelic-client-go/pkg/synthetics"
 	"github.com/newrelic/newrelic-client-go/pkg/workloads"
 )
@@ -31,7 +32,7 @@ type NewRelic struct {
 
 // New returns a collection of New Relic APIs.
 func New(opts ...ConfigOption) (*NewRelic, error) {
-	config := config.Config{}
+	config := config.New()
 
 	// Loop through config options
 	for _, fn := range opts {
@@ -85,10 +86,14 @@ func ConfigAdminAPIKey(adminAPIKey string) ConfigOption {
 }
 
 // ConfigRegion sets the New Relic Region this client will use.
-func ConfigRegion(region config.RegionType) ConfigOption {
+func ConfigRegion(r region.Name) ConfigOption {
 	return func(cfg *config.Config) error {
-		cfg.Region = region
-		return nil
+		if region, ok := region.Regions[r]; ok {
+			regCopy := *region
+			return cfg.SetRegion(&regCopy)
+		}
+
+		return errors.New("unsupported region configured")
 	}
 }
 
@@ -140,7 +145,7 @@ func ConfigServiceName(name string) ConfigOption {
 func ConfigBaseURL(url string) ConfigOption {
 	return func(cfg *config.Config) error {
 		if url != "" {
-			cfg.BaseURL = url
+			cfg.Region().SetRestBaseURL(url)
 			return nil
 		}
 
@@ -152,7 +157,7 @@ func ConfigBaseURL(url string) ConfigOption {
 func ConfigInfrastructureBaseURL(url string) ConfigOption {
 	return func(cfg *config.Config) error {
 		if url != "" {
-			cfg.InfrastructureBaseURL = url
+			cfg.Region().SetInfrastructureBaseURL(url)
 			return nil
 		}
 
@@ -164,7 +169,7 @@ func ConfigInfrastructureBaseURL(url string) ConfigOption {
 func ConfigSyntheticsBaseURL(url string) ConfigOption {
 	return func(cfg *config.Config) error {
 		if url != "" {
-			cfg.SyntheticsBaseURL = url
+			cfg.Region().SetSyntheticsBaseURL(url)
 			return nil
 		}
 
@@ -176,7 +181,7 @@ func ConfigSyntheticsBaseURL(url string) ConfigOption {
 func ConfigNerdGraphBaseURL(url string) ConfigOption {
 	return func(cfg *config.Config) error {
 		if url != "" {
-			cfg.NerdGraphBaseURL = url
+			cfg.Region().SetNerdGraphBaseURL(url)
 			return nil
 		}
 
diff --git a/pkg/alerts/alerts.go b/pkg/alerts/alerts.go
index c5b97ff..1eedb07 100644
--- a/pkg/alerts/alerts.go
+++ b/pkg/alerts/alerts.go
@@ -4,7 +4,6 @@ package alerts
 import (
 	"github.com/newrelic/newrelic-client-go/internal/http"
 	"github.com/newrelic/newrelic-client-go/internal/logging"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 	"github.com/newrelic/newrelic-client-go/pkg/infrastructure"
 )
@@ -12,6 +11,7 @@ import (
 // Alerts is used to communicate with New Relic Alerts.
 type Alerts struct {
 	client      http.Client
+	config      config.Config
 	infraClient http.Client
 	logger      logging.Logger
 	pager       http.Pager
@@ -21,12 +21,6 @@ type Alerts struct {
 func New(config config.Config) Alerts {
 	infraConfig := config
 
-	if infraConfig.InfrastructureBaseURL == "" {
-		infraConfig.InfrastructureBaseURL = infrastructure.BaseURLs[region.Parse(string(config.Region))]
-	}
-
-	infraConfig.BaseURL = infraConfig.InfrastructureBaseURL
-
 	infraClient := http.NewClient(infraConfig)
 	infraClient.SetErrorValue(&infrastructure.ErrorResponse{})
 
@@ -35,6 +29,7 @@ func New(config config.Config) Alerts {
 
 	pkg := Alerts{
 		client:      client,
+		config:      config,
 		infraClient: infraClient,
 		logger:      config.GetLogger(),
 		pager:       &http.LinkHeaderPager{},
@@ -42,6 +37,3 @@ func New(config config.Config) Alerts {
 
 	return pkg
 }
-
-// BaseURLs represents the base API URLs for the different environments of the New Relic REST API V2.
-var BaseURLs = region.DefaultBaseURLs
diff --git a/pkg/alerts/channels.go b/pkg/alerts/channels.go
index a3ed5a4..7a54fa8 100644
--- a/pkg/alerts/channels.go
+++ b/pkg/alerts/channels.go
@@ -80,7 +80,7 @@ func (a *Alerts) ListChannels() ([]*Channel, error) {
 
 	for nextURL != "" {
 		response := alertChannelsResponse{}
-		resp, err := a.client.Get(nextURL, nil, &response)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), nil, &response)
 
 		if err != nil {
 			return nil, err
@@ -121,7 +121,7 @@ func (a *Alerts) CreateChannel(channel Channel) (*Channel, error) {
 	}
 	resp := alertChannelsResponse{}
 
-	_, err := a.client.Post("/alerts_channels.json", nil, &reqBody, &resp)
+	_, err := a.client.Post(a.config.Region().RestURL("alerts_channels.json"), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -134,7 +134,7 @@ func (a *Alerts) CreateChannel(channel Channel) (*Channel, error) {
 func (a *Alerts) DeleteChannel(id int) (*Channel, error) {
 	resp := alertChannelResponse{}
 	url := fmt.Sprintf("/alerts_channels/%d.json", id)
-	_, err := a.client.Delete(url, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/conditions.go b/pkg/alerts/conditions.go
index 72006fc..67ab00c 100644
--- a/pkg/alerts/conditions.go
+++ b/pkg/alerts/conditions.go
@@ -210,7 +210,7 @@ func (a *Alerts) ListConditions(policyID int) ([]*Condition, error) {
 
 	for nextURL != "" {
 		response := alertConditionsResponse{}
-		resp, err := a.client.Get(nextURL, &queryParams, &response)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), &queryParams, &response)
 
 		if err != nil {
 			return nil, err
@@ -248,8 +248,8 @@ func (a *Alerts) CreateCondition(policyID int, condition Condition) (*Condition,
 	}
 	resp := alertConditionResponse{}
 
-	u := fmt.Sprintf("/alerts_conditions/policies/%d.json", policyID)
-	_, err := a.client.Post(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_conditions/policies/%d.json", policyID)
+	_, err := a.client.Post(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -265,8 +265,8 @@ func (a *Alerts) UpdateCondition(condition Condition) (*Condition, error) {
 	}
 	resp := alertConditionResponse{}
 
-	u := fmt.Sprintf("/alerts_conditions/%d.json", condition.ID)
-	_, err := a.client.Put(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_conditions/%d.json", condition.ID)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -278,9 +278,9 @@ func (a *Alerts) UpdateCondition(condition Condition) (*Condition, error) {
 // DeleteCondition delete an alert condition.
 func (a *Alerts) DeleteCondition(id int) (*Condition, error) {
 	resp := alertConditionResponse{}
-	u := fmt.Sprintf("/alerts_conditions/%d.json", id)
+	url := fmt.Sprintf("/alerts_conditions/%d.json", id)
 
-	_, err := a.client.Delete(u, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/incidents.go b/pkg/alerts/incidents.go
index fe95ca4..6e7847b 100644
--- a/pkg/alerts/incidents.go
+++ b/pkg/alerts/incidents.go
@@ -33,7 +33,7 @@ func (a *Alerts) ListIncidents(onlyOpen bool, excludeViolations bool) ([]*Incide
 
 	for nextURL != "" {
 		incidentsResponse := alertIncidentsResponse{}
-		resp, err := a.client.Get(nextURL, queryParams, &incidentsResponse)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), queryParams, &incidentsResponse)
 
 		if err != nil {
 			return nil, err
@@ -60,8 +60,8 @@ func (a *Alerts) CloseIncident(id int) (*Incident, error) {
 
 func (a *Alerts) updateIncident(id int, verb string) (*Incident, error) {
 	response := alertIncidentResponse{}
-	path := fmt.Sprintf("/alerts_incidents/%v/%v.json", id, verb)
-	_, err := a.client.Put(path, nil, nil, &response)
+	url := fmt.Sprintf("/alerts_incidents/%d/%s.json", id, verb)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, nil, &response)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/infrastructure_conditions.go b/pkg/alerts/infrastructure_conditions.go
index 846916b..1d42afb 100644
--- a/pkg/alerts/infrastructure_conditions.go
+++ b/pkg/alerts/infrastructure_conditions.go
@@ -40,7 +40,7 @@ func (a *Alerts) ListInfrastructureConditions(policyID int) ([]InfrastructureCon
 	queryParams := listInfrastructureConditionsParams{
 		PolicyID: policyID,
 	}
-	_, err := a.infraClient.Get("/alerts/conditions", &queryParams, &resp)
+	_, err := a.infraClient.Get(a.config.Region().InfrastructureURL("/alerts/conditions"), &queryParams, &resp)
 
 	if err != nil {
 		return nil, err
@@ -53,7 +53,7 @@ func (a *Alerts) ListInfrastructureConditions(policyID int) ([]InfrastructureCon
 func (a *Alerts) GetInfrastructureCondition(conditionID int) (*InfrastructureCondition, error) {
 	resp := infrastructureConditionResponse{}
 	url := fmt.Sprintf("/alerts/conditions/%d", conditionID)
-	_, err := a.infraClient.Get(url, nil, &resp)
+	_, err := a.infraClient.Get(a.config.Region().InfrastructureURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
@@ -67,7 +67,7 @@ func (a *Alerts) CreateInfrastructureCondition(condition InfrastructureCondition
 	resp := infrastructureConditionResponse{}
 	reqBody := infrastructureConditionRequest{condition}
 
-	_, err := a.infraClient.Post("/alerts/conditions", nil, &reqBody, &resp)
+	_, err := a.infraClient.Post(a.config.Region().InfrastructureURL("/alerts/conditions"), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -82,7 +82,7 @@ func (a *Alerts) UpdateInfrastructureCondition(condition InfrastructureCondition
 	reqBody := infrastructureConditionRequest{condition}
 
 	url := fmt.Sprintf("/alerts/conditions/%d", condition.ID)
-	_, err := a.infraClient.Put(url, nil, &reqBody, &resp)
+	_, err := a.infraClient.Put(a.config.Region().InfrastructureURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -94,7 +94,7 @@ func (a *Alerts) UpdateInfrastructureCondition(condition InfrastructureCondition
 // DeleteInfrastructureCondition is used to delete a New Relic Infrastructure alert condition.
 func (a *Alerts) DeleteInfrastructureCondition(conditionID int) error {
 	url := fmt.Sprintf("/alerts/conditions/%d", conditionID)
-	_, err := a.infraClient.Delete(url, nil, nil)
+	_, err := a.infraClient.Delete(a.config.Region().InfrastructureURL(url), nil, nil)
 
 	if err != nil {
 		return err
diff --git a/pkg/alerts/multi_location_synthetics_conditions.go b/pkg/alerts/multi_location_synthetics_conditions.go
index 75333a3..699b47f 100644
--- a/pkg/alerts/multi_location_synthetics_conditions.go
+++ b/pkg/alerts/multi_location_synthetics_conditions.go
@@ -38,7 +38,7 @@ func (a *Alerts) ListMultiLocationSyntheticsConditions(policyID int) ([]*MultiLo
 	nextURL := fmt.Sprintf("/alerts_location_failure_conditions/policies/%d.json", policyID)
 
 	for nextURL != "" {
-		resp, err := a.client.Get(nextURL, &queryParams, &response)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), &queryParams, &response)
 
 		if err != nil {
 			return nil, err
@@ -60,8 +60,8 @@ func (a *Alerts) CreateMultiLocationSyntheticsCondition(condition MultiLocationS
 	}
 	resp := multiLocationSyntheticsConditionCreateResponse{}
 
-	u := fmt.Sprintf("/alerts_location_failure_conditions/policies/%d.json", policyID)
-	_, err := a.client.Post(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_location_failure_conditions/policies/%d.json", policyID)
+	_, err := a.client.Post(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 	if err != nil {
 		return nil, err
 	}
@@ -76,8 +76,8 @@ func (a *Alerts) UpdateMultiLocationSyntheticsCondition(condition MultiLocationS
 	}
 	resp := multiLocationSyntheticsConditionCreateResponse{}
 
-	u := fmt.Sprintf("/alerts_location_failure_conditions/%d.json", condition.ID)
-	_, err := a.client.Put(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_location_failure_conditions/%d.json", condition.ID)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -89,9 +89,9 @@ func (a *Alerts) UpdateMultiLocationSyntheticsCondition(condition MultiLocationS
 // DeleteMultiLocationSyntheticsCondition delete an alert condition.
 func (a *Alerts) DeleteMultiLocationSyntheticsCondition(conditionID int) (*MultiLocationSyntheticsCondition, error) {
 	resp := multiLocationSyntheticsConditionCreateResponse{}
-	u := fmt.Sprintf("/alerts_conditions/%d.json", conditionID)
+	url := fmt.Sprintf("/alerts_conditions/%d.json", conditionID)
 
-	_, err := a.client.Delete(u, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/nrql_conditions.go b/pkg/alerts/nrql_conditions.go
index c4836b1..1f337a2 100644
--- a/pkg/alerts/nrql_conditions.go
+++ b/pkg/alerts/nrql_conditions.go
@@ -209,7 +209,7 @@ func (a *Alerts) ListNrqlConditions(policyID int) ([]*NrqlCondition, error) {
 
 	for nextURL != "" {
 		response := nrqlConditionsResponse{}
-		resp, err := a.client.Get(nextURL, &queryParams, &response)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), &queryParams, &response)
 
 		if err != nil {
 			return nil, err
@@ -248,8 +248,8 @@ func (a *Alerts) CreateNrqlCondition(policyID int, condition NrqlCondition) (*Nr
 	}
 	resp := nrqlConditionResponse{}
 
-	u := fmt.Sprintf("/alerts_nrql_conditions/policies/%d.json", policyID)
-	_, err := a.client.Post(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_nrql_conditions/policies/%d.json", policyID)
+	_, err := a.client.Post(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -265,8 +265,8 @@ func (a *Alerts) UpdateNrqlCondition(condition NrqlCondition) (*NrqlCondition, e
 	}
 	resp := nrqlConditionResponse{}
 
-	u := fmt.Sprintf("/alerts_nrql_conditions/%d.json", condition.ID)
-	_, err := a.client.Put(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_nrql_conditions/%d.json", condition.ID)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -278,9 +278,9 @@ func (a *Alerts) UpdateNrqlCondition(condition NrqlCondition) (*NrqlCondition, e
 // DeleteNrqlCondition deletes a NRQL alert condition.
 func (a *Alerts) DeleteNrqlCondition(id int) (*NrqlCondition, error) {
 	resp := nrqlConditionResponse{}
-	u := fmt.Sprintf("/alerts_nrql_conditions/%d.json", id)
+	url := fmt.Sprintf("/alerts_nrql_conditions/%d.json", id)
 
-	_, err := a.client.Delete(u, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/plugins_conditions.go b/pkg/alerts/plugins_conditions.go
index 19b40e3..2487baf 100644
--- a/pkg/alerts/plugins_conditions.go
+++ b/pkg/alerts/plugins_conditions.go
@@ -37,7 +37,7 @@ func (a *Alerts) ListPluginsConditions(policyID int) ([]*PluginsCondition, error
 
 	for nextURL != "" {
 		response := pluginsConditionsResponse{}
-		resp, err := a.client.Get(nextURL, &queryParams, &response)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), &queryParams, &response)
 
 		if err != nil {
 			return nil, err
@@ -77,8 +77,8 @@ func (a *Alerts) CreatePluginsCondition(policyID int, condition PluginsCondition
 	}
 	resp := pluginConditionResponse{}
 
-	u := fmt.Sprintf("/alerts_plugins_conditions/policies/%d.json", policyID)
-	_, err := a.client.Post(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_plugins_conditions/policies/%d.json", policyID)
+	_, err := a.client.Post(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -94,8 +94,8 @@ func (a *Alerts) UpdatePluginsCondition(condition PluginsCondition) (*PluginsCon
 	}
 	resp := pluginConditionResponse{}
 
-	u := fmt.Sprintf("/alerts_plugins_conditions/%d.json", condition.ID)
-	_, err := a.client.Put(u, nil, &reqBody, &resp)
+	url := fmt.Sprintf("/alerts_plugins_conditions/%d.json", condition.ID)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -107,9 +107,9 @@ func (a *Alerts) UpdatePluginsCondition(condition PluginsCondition) (*PluginsCon
 // DeletePluginsCondition deletes a plugin alert condition.
 func (a *Alerts) DeletePluginsCondition(id int) (*PluginsCondition, error) {
 	resp := pluginConditionResponse{}
-	u := fmt.Sprintf("/alerts_plugins_conditions/%d.json", id)
+	url := fmt.Sprintf("/alerts_plugins_conditions/%d.json", id)
 
-	_, err := a.client.Delete(u, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/policies.go b/pkg/alerts/policies.go
index d6b9ac1..bac6ded 100644
--- a/pkg/alerts/policies.go
+++ b/pkg/alerts/policies.go
@@ -43,7 +43,7 @@ type ListPoliciesParams struct {
 func (a *Alerts) ListPolicies(params *ListPoliciesParams) ([]Policy, error) {
 	alertPolicies := []Policy{}
 
-	nextURL := "/alerts_policies.json"
+	nextURL := a.config.Region().RestURL("/alerts_policies.json")
 
 	for nextURL != "" {
 		response := alertPoliciesResponse{}
@@ -86,7 +86,7 @@ func (a *Alerts) CreatePolicy(policy Policy) (*Policy, error) {
 	}
 	resp := alertPolicyResponse{}
 
-	_, err := a.client.Post("/alerts_policies.json", nil, &reqBody, &resp)
+	_, err := a.client.Post(a.config.Region().RestURL("/alerts_policies.json"), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -104,7 +104,7 @@ func (a *Alerts) UpdatePolicy(policy Policy) (*Policy, error) {
 	resp := alertPolicyResponse{}
 	url := fmt.Sprintf("/alerts_policies/%d.json", policy.ID)
 
-	_, err := a.client.Put(url, nil, &reqBody, &resp)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 	if err != nil {
 		return nil, err
 	}
@@ -117,7 +117,7 @@ func (a *Alerts) DeletePolicy(id int) (*Policy, error) {
 	resp := alertPolicyResponse{}
 	url := fmt.Sprintf("/alerts_policies/%d.json", id)
 
-	_, err := a.client.Delete(url, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/alerts/policy_channels.go b/pkg/alerts/policy_channels.go
index a0461d2..0253e7d 100644
--- a/pkg/alerts/policy_channels.go
+++ b/pkg/alerts/policy_channels.go
@@ -25,7 +25,7 @@ func (a *Alerts) UpdatePolicyChannels(policyID int, channelIDs []int) (*PolicyCh
 
 	resp := updatePolicyChannelsResponse{}
 
-	_, err := a.client.Put("/alerts_policy_channels.json", &queryParams, nil, &resp)
+	_, err := a.client.Put(a.config.Region().RestURL("/alerts_policy_channels.json"), &queryParams, nil, &resp)
 
 	if err != nil {
 		return nil, err
@@ -44,7 +44,7 @@ func (a *Alerts) DeletePolicyChannel(policyID int, channelID int) (*Channel, err
 
 	resp := deletePolicyChannelResponse{}
 
-	_, err := a.client.Delete("/alerts_policy_channels.json", &queryParams, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL("/alerts_policy_channels.json"), &queryParams, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/alerts/synthetics_conditions.go b/pkg/alerts/synthetics_conditions.go
index b40ce1f..0a33fd4 100644
--- a/pkg/alerts/synthetics_conditions.go
+++ b/pkg/alerts/synthetics_conditions.go
@@ -25,7 +25,7 @@ func (a *Alerts) ListSyntheticsConditions(policyID int) ([]*SyntheticsCondition,
 
 	for nextURL != "" {
 		response := syntheticsConditionsResponse{}
-		resp, err := a.client.Get(nextURL, &queryParams, &response)
+		resp, err := a.client.Get(a.config.Region().RestURL(nextURL), &queryParams, &response)
 
 		if err != nil {
 			return nil, err
@@ -62,7 +62,7 @@ func (a *Alerts) CreateSyntheticsCondition(policyID int, condition SyntheticsCon
 	resp := syntheticsConditionResponse{}
 	reqBody := syntheticsConditionRequest{condition}
 	url := fmt.Sprintf("/alerts_synthetics_conditions/policies/%d.json", policyID)
-	_, err := a.client.Post(url, nil, &reqBody, &resp)
+	_, err := a.client.Post(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -76,7 +76,7 @@ func (a *Alerts) UpdateSyntheticsCondition(condition SyntheticsCondition) (*Synt
 	resp := syntheticsConditionResponse{}
 	reqBody := syntheticsConditionRequest{condition}
 	url := fmt.Sprintf("/alerts_synthetics_conditions/%d.json", condition.ID)
-	_, err := a.client.Put(url, nil, &reqBody, &resp)
+	_, err := a.client.Put(a.config.Region().RestURL(url), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -89,7 +89,7 @@ func (a *Alerts) UpdateSyntheticsCondition(condition SyntheticsCondition) (*Synt
 func (a *Alerts) DeleteSyntheticsCondition(conditionID int) (*SyntheticsCondition, error) {
 	resp := syntheticsConditionResponse{}
 	url := fmt.Sprintf("/alerts_synthetics_conditions/%d.json", conditionID)
-	_, err := a.client.Delete(url, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/apm/apm.go b/pkg/apm/apm.go
index c028b1d..f5456b3 100644
--- a/pkg/apm/apm.go
+++ b/pkg/apm/apm.go
@@ -3,13 +3,13 @@ package apm
 
 import (
 	"github.com/newrelic/newrelic-client-go/internal/http"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
 // APM is used to communicate with the New Relic APM product.
 type APM struct {
 	client http.Client
+	config config.Config
 	pager  http.Pager
 }
 
@@ -19,11 +19,9 @@ func New(config config.Config) APM {
 
 	pkg := APM{
 		client: client,
+		config: config,
 		pager:  &http.LinkHeaderPager{},
 	}
 
 	return pkg
 }
-
-// BaseURLs represents the base API URLs for the different environments of the New Relic REST API V2.
-var BaseURLs = region.DefaultBaseURLs
diff --git a/pkg/apm/applications_metrics.go b/pkg/apm/applications_metrics.go
index 3412530..d49634e 100644
--- a/pkg/apm/applications_metrics.go
+++ b/pkg/apm/applications_metrics.go
@@ -1,7 +1,7 @@
 package apm
 
 import (
-	"fmt"
+	"strconv"
 	"time"
 )
 
@@ -53,13 +53,13 @@ type MetricTimesliceValues struct {
 // GetMetricNames is used to retrieve a list of known metrics and their value names for the given resource.
 //
 // https://rpm.newrelic.com/api/explore/applications/metric_names
-func (apm *APM) GetMetricNames(applicationID int, params MetricNamesParams) ([]*MetricName, error) {
+func (a *APM) GetMetricNames(applicationID int, params MetricNamesParams) ([]*MetricName, error) {
+	nextURL := a.config.Region().RestURL("applications", strconv.Itoa(applicationID), "metrics.json")
 	response := metricNamesResponse{}
 	metrics := []*MetricName{}
-	nextURL := fmt.Sprintf("/applications/%d/metrics.json", applicationID)
 
 	for nextURL != "" {
-		resp, err := apm.client.Get(nextURL, &params, &response)
+		resp, err := a.client.Get(nextURL, &params, &response)
 
 		if err != nil {
 			return nil, err
@@ -67,7 +67,7 @@ func (apm *APM) GetMetricNames(applicationID int, params MetricNamesParams) ([]*
 
 		metrics = append(metrics, response.Metrics...)
 
-		paging := apm.pager.Parse(resp)
+		paging := a.pager.Parse(resp)
 		nextURL = paging.Next
 	}
 
@@ -77,13 +77,14 @@ func (apm *APM) GetMetricNames(applicationID int, params MetricNamesParams) ([]*
 // GetMetricData is used to retrieve a list of values for each of the requested metrics.
 //
 // https://rpm.newrelic.com/api/explore/applications/metric_data
-func (apm *APM) GetMetricData(applicationID int, params MetricDataParams) ([]*MetricData, error) {
+func (a *APM) GetMetricData(applicationID int, params MetricDataParams) ([]*MetricData, error) {
+	nextURL := a.config.Region().RestURL("applications", strconv.Itoa(applicationID), "/metrics/data.json")
+
 	response := metricDataResponse{}
 	data := []*MetricData{}
-	nextURL := fmt.Sprintf("/applications/%d/metrics/data.json", applicationID)
 
 	for nextURL != "" {
-		resp, err := apm.client.Get(nextURL, &params, &response)
+		resp, err := a.client.Get(nextURL, &params, &response)
 
 		if err != nil {
 			return nil, err
@@ -91,7 +92,7 @@ func (apm *APM) GetMetricData(applicationID int, params MetricDataParams) ([]*Me
 
 		data = append(data, response.MetricData.Metrics...)
 
-		paging := apm.pager.Parse(resp)
+		paging := a.pager.Parse(resp)
 		nextURL = paging.Next
 	}
 
diff --git a/pkg/apm/applications_rest.go b/pkg/apm/applications_rest.go
index e22416d..720e8b7 100644
--- a/pkg/apm/applications_rest.go
+++ b/pkg/apm/applications_rest.go
@@ -12,7 +12,7 @@ type applicationsREST struct {
 // list is used to retrieve New Relic applications.
 func (a *applicationsREST) list(accountID int, params *ListApplicationsParams) ([]*Application, error) {
 	apps := []*Application{}
-	nextURL := "/applications.json"
+	nextURL := a.parent.config.Region().RestURL("applications.json")
 
 	for nextURL != "" {
 		response := applicationsResponse{}
@@ -46,7 +46,7 @@ func (a *applicationsREST) get(accountID int, applicationID int) (*Application,
 	response := applicationResponse{}
 	url := fmt.Sprintf("/applications/%d.json", applicationID)
 
-	_, err := a.parent.client.Get(url, nil, &response)
+	_, err := a.parent.client.Get(a.parent.config.Region().RestURL(url), nil, &response)
 
 	if err != nil {
 		return nil, err
@@ -58,12 +58,12 @@ func (a *applicationsREST) get(accountID int, applicationID int) (*Application,
 // update is used to update a New Relic application's name and/or settings.
 func (a *applicationsREST) update(accountID int, applicationID int, params UpdateApplicationParams) (*Application, error) {
 	response := applicationResponse{}
-	url := fmt.Sprintf("/applications/%d.json", applicationID)
 	reqBody := updateApplicationRequest{
 		Fields: updateApplicationFields(params),
 	}
+	url := fmt.Sprintf("/applications/%d.json", applicationID)
 
-	_, err := a.parent.client.Put(url, nil, &reqBody, &response)
+	_, err := a.parent.client.Put(a.parent.config.Region().RestURL(url), nil, &reqBody, &response)
 
 	if err != nil {
 		return nil, err
@@ -78,7 +78,7 @@ func (a *applicationsREST) remove(accountID int, applicationID int) (*Applicatio
 	response := applicationResponse{}
 	url := fmt.Sprintf("/applications/%d.json", applicationID)
 
-	_, err := a.parent.client.Delete(url, nil, &response)
+	_, err := a.parent.client.Delete(a.parent.config.Region().RestURL(url), nil, &response)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/apm/deployments.go b/pkg/apm/deployments.go
index 2df3044..24738aa 100644
--- a/pkg/apm/deployments.go
+++ b/pkg/apm/deployments.go
@@ -2,6 +2,7 @@ package apm
 
 import (
 	"fmt"
+	"strconv"
 
 	"github.com/newrelic/newrelic-client-go/internal/http"
 )
@@ -25,7 +26,7 @@ type DeploymentLinks struct {
 // ListDeployments returns deployments for an application.
 func (a *APM) ListDeployments(applicationID int) ([]*Deployment, error) {
 	deployments := []*Deployment{}
-	nextURL := fmt.Sprintf("/applications/%d/deployments.json", applicationID)
+	nextURL := a.config.Region().RestURL("applications", strconv.Itoa(applicationID), "deployments.json")
 
 	for nextURL != "" {
 		response := deploymentsResponse{}
@@ -58,8 +59,8 @@ func (a *APM) CreateDeployment(applicationID int, deployment Deployment) (*Deplo
 	}
 	resp := deploymentResponse{}
 
-	u := fmt.Sprintf("/applications/%d/deployments.json", applicationID)
-	req, err := http.NewRequest(a.client, "POST", u, nil, &reqBody, &resp)
+	url := a.config.Region().RestURL("applications", strconv.Itoa(applicationID), "deployments.json")
+	req, err := http.NewRequest(a.client, "POST", url, nil, &reqBody, &resp)
 	if err != nil {
 		return nil, err
 	}
@@ -78,9 +79,9 @@ func (a *APM) CreateDeployment(applicationID int, deployment Deployment) (*Deplo
 // DeleteDeployment deletes a deployment marker for an application.
 func (a *APM) DeleteDeployment(applicationID int, deploymentID int) (*Deployment, error) {
 	resp := deploymentResponse{}
-	u := fmt.Sprintf("/applications/%d/deployments/%d.json", applicationID, deploymentID)
+	url := a.config.Region().RestURL("applications", strconv.Itoa(applicationID), "deployments", fmt.Sprintf("%d.json", deploymentID))
 
-	req, err := http.NewRequest(a.client, "DELETE", u, nil, nil, &resp)
+	req, err := http.NewRequest(a.client, "DELETE", url, nil, nil, &resp)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/apm/key_transactions.go b/pkg/apm/key_transactions.go
index aa0d362..c386288 100644
--- a/pkg/apm/key_transactions.go
+++ b/pkg/apm/key_transactions.go
@@ -32,7 +32,7 @@ type ListKeyTransactionsParams struct {
 // ListKeyTransactions returns all key transactions for an account.
 func (a *APM) ListKeyTransactions(params *ListKeyTransactionsParams) ([]*KeyTransaction, error) {
 	results := []*KeyTransaction{}
-	nextURL := "/key_transactions.json"
+	nextURL := a.config.Region().RestURL("key_transactions.json")
 
 	for nextURL != "" {
 		response := keyTransactionsResponse{}
@@ -54,9 +54,9 @@ func (a *APM) ListKeyTransactions(params *ListKeyTransactionsParams) ([]*KeyTran
 // GetKeyTransaction returns a specific key transaction by ID.
 func (a *APM) GetKeyTransaction(id int) (*KeyTransaction, error) {
 	response := keyTransactionResponse{}
-	u := fmt.Sprintf("/key_transactions/%d.json", id)
+	url := fmt.Sprintf("/key_transactions/%d.json", id)
 
-	_, err := a.client.Get(u, nil, &response)
+	_, err := a.client.Get(a.config.Region().RestURL(url), nil, &response)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/apm/labels.go b/pkg/apm/labels.go
index 2a1bf00..dbd6710 100644
--- a/pkg/apm/labels.go
+++ b/pkg/apm/labels.go
@@ -1,8 +1,6 @@
 package apm
 
 import (
-	"fmt"
-
 	"github.com/newrelic/newrelic-client-go/pkg/errors"
 )
 
@@ -23,7 +21,7 @@ type LabelLinks struct {
 // ListLabels returns the labels within an account.
 func (a *APM) ListLabels() ([]*Label, error) {
 	labels := []*Label{}
-	nextURL := "/labels.json"
+	nextURL := a.config.Region().RestURL("labels.json")
 
 	for nextURL != "" {
 		response := labelsResponse{}
@@ -68,7 +66,7 @@ func (a *APM) CreateLabel(label Label) (*Label, error) {
 	resp := labelResponse{}
 
 	// The API currently uses a PUT request for label creation
-	_, err := a.client.Put("/labels.json", nil, &reqBody, &resp)
+	_, err := a.client.Put(a.config.Region().RestURL("labels.json"), nil, &reqBody, &resp)
 
 	if err != nil {
 		return nil, err
@@ -82,8 +80,7 @@ func (a *APM) CreateLabel(label Label) (*Label, error) {
 func (a *APM) DeleteLabel(key string) (*Label, error) {
 	resp := labelResponse{}
 
-	u := fmt.Sprintf("/labels/%s.json", key)
-	_, err := a.client.Delete(u, nil, &resp)
+	_, err := a.client.Delete(a.config.Region().RestURL("labels", key+".json"), nil, &resp)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/config/config.go b/pkg/config/config.go
index d4a5295..8d2bd7d 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/newrelic/newrelic-client-go/internal/logging"
 	"github.com/newrelic/newrelic-client-go/internal/version"
+	"github.com/newrelic/newrelic-client-go/pkg/region"
 )
 
 // Config contains all the configuration data for the API Client.
@@ -20,8 +21,8 @@ type Config struct {
 	// see: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys#admin
 	AdminAPIKey string
 
-	// Region of the New Relic platform to use
-	Region RegionType
+	// region of the New Relic platform to use
+	region *region.Region
 
 	// Timeout is the client timeout for HTTP requests.
 	Timeout *time.Duration
@@ -32,22 +33,6 @@ type Config struct {
 	// UserAgent updates the default user agent string used by the client.
 	UserAgent string
 
-	// BaseURL updates the default base URL used by the client during requests to
-	// the V2 REST API.
-	BaseURL string
-
-	// SyntheticsBaseURL updates the default base URL used by the client during
-	// requests to the Synthetics API.
-	SyntheticsBaseURL string
-
-	// InfrastructureBaseURL updates the default base URL used by the client during
-	// requests to the Infrastructure API.
-	InfrastructureBaseURL string
-
-	// NerdGraph updates the default base URL used by the client during requests
-	// to the NerdGraph API.
-	NerdGraphBaseURL string
-
 	// ServiceName is for New Relic internal use only.
 	ServiceName string
 
@@ -62,16 +47,37 @@ type Config struct {
 	Logger logging.Logger
 }
 
-// RegionType represents a New Relic region.
-type RegionType string
+// New creates a default configuration and returns it
+func New() Config {
+	regCopy := *region.Default
+
+	return Config{
+		region:    &regCopy,
+		UserAgent: "newrelic/newrelic-client-go",
+		LogLevel:  "info",
+	}
+}
+
+// Region returns the region configuration struct
+// if one has not been set, use the default region
+func (c *Config) Region() *region.Region {
+	if c.region == nil {
+		regCopy := *region.Default
+		c.region = &regCopy
+	}
+
+	return c.region
+}
+
+// SetRegion configures the region
+func (c *Config) SetRegion(reg *region.Region) error {
+	if reg == nil {
+		return region.ErrorNil()
+	}
+
+	c.region = reg
 
-// RegionTypes contains the possible values for New Relic region.
-var RegionTypes = struct {
-	US RegionType
-	EU RegionType
-}{
-	US: "US",
-	EU: "EU",
+	return nil
 }
 
 // GetLogger returns a logger instance based on the config values.
diff --git a/pkg/dashboards/dashboard.go b/pkg/dashboards/dashboard.go
index bb6cbb3..59ad738 100644
--- a/pkg/dashboards/dashboard.go
+++ b/pkg/dashboards/dashboard.go
@@ -22,7 +22,7 @@ type ListDashboardsParams struct {
 // ListDashboards is used to retrieve New Relic dashboards.
 func (d *Dashboards) ListDashboards(params *ListDashboardsParams) ([]*Dashboard, error) {
 	dashboard := []*Dashboard{}
-	nextURL := "/dashboards.json"
+	nextURL := d.config.Region().RestURL("dashboards.json")
 
 	for nextURL != "" {
 		response := dashboardsResponse{}
@@ -46,7 +46,7 @@ func (d *Dashboards) GetDashboard(dashboardID int) (*Dashboard, error) {
 	response := dashboardResponse{}
 	url := fmt.Sprintf("/dashboards/%d.json", dashboardID)
 
-	_, err := d.client.Get(url, nil, &response)
+	_, err := d.client.Get(d.config.Region().RestURL(url), nil, &response)
 
 	if err != nil {
 		return nil, err
@@ -61,7 +61,7 @@ func (d *Dashboards) CreateDashboard(dashboard Dashboard) (*Dashboard, error) {
 	reqBody := dashboardRequest{
 		Dashboard: dashboard,
 	}
-	_, err := d.client.Post("/dashboards.json", nil, &reqBody, &response)
+	_, err := d.client.Post(d.config.Region().RestURL("dashboards.json"), nil, &reqBody, &response)
 
 	if err != nil {
 		return nil, err
@@ -78,7 +78,7 @@ func (d *Dashboards) UpdateDashboard(dashboard Dashboard) (*Dashboard, error) {
 		Dashboard: dashboard,
 	}
 
-	_, err := d.client.Put(url, nil, &reqBody, &response)
+	_, err := d.client.Put(d.config.Region().RestURL(url), nil, &reqBody, &response)
 
 	if err != nil {
 		return nil, err
@@ -92,7 +92,7 @@ func (d *Dashboards) DeleteDashboard(dashboardID int) (*Dashboard, error) {
 	response := dashboardResponse{}
 	url := fmt.Sprintf("/dashboards/%d.json", dashboardID)
 
-	_, err := d.client.Delete(url, nil, &response)
+	_, err := d.client.Delete(d.config.Region().RestURL(url), nil, &response)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/dashboards/dashboards.go b/pkg/dashboards/dashboards.go
index 0eae1d6..66c638b 100644
--- a/pkg/dashboards/dashboards.go
+++ b/pkg/dashboards/dashboards.go
@@ -4,13 +4,13 @@ package dashboards
 import (
 	"github.com/newrelic/newrelic-client-go/internal/http"
 	"github.com/newrelic/newrelic-client-go/internal/logging"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
 // Dashboards is used to communicate with the New Relic Dashboards product.
 type Dashboards struct {
 	client http.Client
+	config config.Config
 	logger logging.Logger
 	pager  http.Pager
 }
@@ -19,12 +19,10 @@ type Dashboards struct {
 func New(config config.Config) Dashboards {
 	pkg := Dashboards{
 		client: http.NewClient(config),
+		config: config,
 		logger: config.GetLogger(),
 		pager:  &http.LinkHeaderPager{},
 	}
 
 	return pkg
 }
-
-// BaseURLs represents the base API URLs for the different environments of the New Relic REST API V2.
-var BaseURLs = region.DefaultBaseURLs
diff --git a/pkg/entities/entities.go b/pkg/entities/entities.go
index 715fa2a..4b59168 100644
--- a/pkg/entities/entities.go
+++ b/pkg/entities/entities.go
@@ -4,7 +4,6 @@ package entities
 import (
 	"github.com/newrelic/newrelic-client-go/internal/http"
 	"github.com/newrelic/newrelic-client-go/internal/logging"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
@@ -21,6 +20,3 @@ func New(config config.Config) Entities {
 		logger: config.GetLogger(),
 	}
 }
-
-// BaseURLs represents the base API URLs for the different environments of the New Relic NerdGraph API.
-var BaseURLs = region.NerdGraphBaseURLs
diff --git a/pkg/infrastructure/infrastructure.go b/pkg/infrastructure/infrastructure.go
index 4ace993..9bcb696 100644
--- a/pkg/infrastructure/infrastructure.go
+++ b/pkg/infrastructure/infrastructure.go
@@ -3,16 +3,8 @@ package infrastructure
 
 import (
 	"github.com/newrelic/newrelic-client-go/internal/http"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 )
 
-// BaseURLs describes the base URLs for the Infrastructure Alerts API.
-var BaseURLs = map[region.Region]string{
-	region.US:      "https://infra-api.newrelic.com/v2",
-	region.EU:      "https://infra-api.eu.newrelic.com/v2",
-	region.Staging: "https://staging-infra-api.newrelic.com/v2",
-}
-
 // ErrorResponse represents an error response from New Relic Infrastructure.
 type ErrorResponse struct {
 	Errors  []*ErrorDetail `json:"errors,omitempty"`
diff --git a/pkg/plugins/components.go b/pkg/plugins/components.go
index 431074f..13cb9cf 100644
--- a/pkg/plugins/components.go
+++ b/pkg/plugins/components.go
@@ -2,6 +2,7 @@ package plugins
 
 import (
 	"fmt"
+	"strconv"
 	"time"
 )
 
@@ -18,7 +19,7 @@ type ListComponentsParams struct {
 // a New Relic account.
 func (p *Plugins) ListComponents(params *ListComponentsParams) ([]*Component, error) {
 	c := []*Component{}
-	nextURL := "/components.json"
+	nextURL := p.config.Region().RestURL("components.json")
 
 	for nextURL != "" {
 		response := componentsResponse{}
@@ -43,7 +44,7 @@ func (p *Plugins) GetComponent(componentID int) (*Component, error) {
 	response := componentResponse{}
 	url := fmt.Sprintf("/components/%d.json", componentID)
 
-	_, err := p.client.Get(url, nil, &response)
+	_, err := p.client.Get(p.config.Region().RestURL(url), nil, &response)
 
 	if err != nil {
 		return nil, err
@@ -63,7 +64,7 @@ type ListComponentMetricsParams struct {
 func (p *Plugins) ListComponentMetrics(componentID int, params *ListComponentMetricsParams) ([]*ComponentMetric, error) {
 	m := []*ComponentMetric{}
 	response := componentMetricsResponse{}
-	nextURL := fmt.Sprintf("/components/%d/metrics.json", componentID)
+	nextURL := p.config.Region().RestURL("components", strconv.Itoa(componentID), "metrics.json")
 
 	for nextURL != "" {
 		resp, err := p.client.Get(nextURL, &params, &response)
@@ -111,7 +112,7 @@ type GetComponentMetricDataParams struct {
 func (p *Plugins) GetComponentMetricData(componentID int, params *GetComponentMetricDataParams) ([]*Metric, error) {
 	m := []*Metric{}
 	response := componentMetricDataResponse{}
-	nextURL := fmt.Sprintf("/components/%d/metrics/data.json", componentID)
+	nextURL := p.config.Region().RestURL("components", strconv.Itoa(componentID), "metrics/data.json")
 
 	for nextURL != "" {
 		resp, err := p.client.Get(nextURL, &params, &response)
diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go
index c390ef0..64fe1d9 100644
--- a/pkg/plugins/plugins.go
+++ b/pkg/plugins/plugins.go
@@ -12,6 +12,7 @@ import (
 // Plugins is used to communicate with the New Relic Plugins product.
 type Plugins struct {
 	client http.Client
+	config config.Config
 	logger logging.Logger
 	pager  http.Pager
 }
@@ -20,6 +21,7 @@ type Plugins struct {
 func New(config config.Config) Plugins {
 	pkg := Plugins{
 		client: http.NewClient(config),
+		config: config,
 		logger: config.GetLogger(),
 		pager:  &http.LinkHeaderPager{},
 	}
@@ -41,7 +43,7 @@ type ListPluginsParams struct {
 // with metadata pertaining to each plugin.
 func (p *Plugins) ListPlugins(params *ListPluginsParams) ([]*Plugin, error) {
 	results := []*Plugin{}
-	nextURL := "/plugins.json"
+	nextURL := p.config.Region().RestURL("plugins.json")
 
 	for nextURL != "" {
 		response := pluginsResponse{}
@@ -72,8 +74,8 @@ type GetPluginParams struct {
 func (p *Plugins) GetPlugin(id int, params *GetPluginParams) (*Plugin, error) {
 	response := pluginResponse{}
 
-	u := fmt.Sprintf("/plugins/%d.json", id)
-	_, err := p.client.Get(u, &params, &response)
+	url := fmt.Sprintf("/plugins/%d.json", id)
+	_, err := p.client.Get(p.config.Region().RestURL(url), &params, &response)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/region/errors.go b/pkg/region/errors.go
new file mode 100644
index 0000000..db8c91b
--- /dev/null
+++ b/pkg/region/errors.go
@@ -0,0 +1,26 @@
+package region
+
+import (
+	"fmt"
+)
+
+// InvalidError returns when the Region is not valid
+type InvalidError struct {
+	Message string
+}
+
+// Error string reported when an InvalidError happens
+func (e InvalidError) Error() string {
+	if e.Message != "" {
+		return fmt.Sprintf("invalid region: %s", e.Message)
+	}
+
+	return "invalid region"
+}
+
+// ErrorNil returns an InvalidError message saying the value was nil
+func ErrorNil() InvalidError {
+	return InvalidError{
+		Message: "value is nil",
+	}
+}
diff --git a/pkg/region/region.go b/pkg/region/region.go
new file mode 100644
index 0000000..83c8d8c
--- /dev/null
+++ b/pkg/region/region.go
@@ -0,0 +1,158 @@
+// Package region describes the operational regions defined for New Relic
+//
+// Regions are geographical locations where the New Relic platform operates
+// and this package provides an abstraction layer for handling them within
+// the New Relic Client and underlying APIs
+package region
+
+import (
+	"errors"
+	"strings"
+
+	log "github.com/sirupsen/logrus"
+)
+
+// Name is the name of a New Relic region
+type Name string
+
+// Region represents the members of the Region enumeration.
+type Region struct {
+	name                  string
+	restBaseURL           string
+	infrastructureBaseURL string
+	syntheticsBaseURL     string
+	nerdGraphBaseURL      string
+}
+
+// String returns a human readable value for the specified Region
+func (r *Region) String() string {
+	if r != nil && r.name != "" {
+		return r.name
+	}
+
+	return "(Unknown)"
+}
+
+//
+// NerdGraph - the future
+//
+
+// SetNerdGraphBaseURL Allows overriding the NerdGraph Base URL
+func (r *Region) SetNerdGraphBaseURL(url string) {
+	if r != nil && url != "" {
+		r.nerdGraphBaseURL = url
+	}
+}
+
+// NerdGraphURL returns the Full URL for Infrastructure REST API Calls, with any additional path elements appended
+func (r *Region) NerdGraphURL(path ...string) string {
+	if r == nil {
+		log.Errorf("call to nil region.NerdGraphURL")
+		return ""
+	}
+
+	url, err := concatURLPaths(r.nerdGraphBaseURL, path)
+	if err != nil {
+		log.Errorf("unable to make URL with error: %s", err)
+		return r.nerdGraphBaseURL
+	}
+
+	return url
+}
+
+//
+// REST
+//
+
+// SetRestBaseURL Allows overriding the REST Base URL
+func (r *Region) SetRestBaseURL(url string) {
+	if r != nil && url != "" {
+		r.restBaseURL = url
+	}
+}
+
+// RestURL returns the Full URL for REST API Calls, with any additional path elements appended
+func (r *Region) RestURL(path ...string) string {
+	if r == nil {
+		log.Errorf("call to nil region.RestURL")
+		return ""
+	}
+
+	url, err := concatURLPaths(r.restBaseURL, path)
+	if err != nil {
+		log.Errorf("unable to make URL with error: %s", err)
+		return r.restBaseURL
+	}
+
+	return url
+}
+
+//
+// Infrastructure
+//
+
+// SetInfrastructureBaseURL Allows overriding the Infrastructure Base URL
+func (r *Region) SetInfrastructureBaseURL(url string) {
+	if r != nil && url != "" {
+		r.infrastructureBaseURL = url
+	}
+}
+
+// InfrastructureURL returns the Full URL for Infrastructure REST API Calls, with any additional path elements appended
+func (r *Region) InfrastructureURL(path ...string) string {
+	if r == nil {
+		log.Errorf("call to nil region.InfrastructureURL")
+		return ""
+	}
+
+	url, err := concatURLPaths(r.infrastructureBaseURL, path)
+	if err != nil {
+		log.Errorf("unable to make URL with error: %s", err)
+		return r.infrastructureBaseURL
+	}
+
+	return url
+}
+
+//
+// Synthetics
+//
+
+// SetSyntheticsBaseURL Allows overriding the Synthetics Base URL
+func (r *Region) SetSyntheticsBaseURL(url string) {
+	if r != nil && url != "" {
+		r.syntheticsBaseURL = url
+	}
+}
+
+// SyntheticsURL returns the Full URL for Infrastructure REST API Calls, with any additional path elements appended
+func (r *Region) SyntheticsURL(path ...string) string {
+	if r == nil {
+		log.Errorf("call to nil region.SyntheticsURL")
+		return ""
+	}
+
+	url, err := concatURLPaths(r.syntheticsBaseURL, path)
+	if err != nil {
+		log.Errorf("unable to make URL with error: %s", err)
+		return r.syntheticsBaseURL
+	}
+
+	return url
+}
+
+// concatURLPaths is a helper function for the URL builders below
+func concatURLPaths(host string, path []string) (string, error) {
+	if host == "" {
+		return "", errors.New("host can not be empty")
+	}
+
+	elements := make([]string, len(path)+1)
+	elements[0] = strings.TrimSuffix(host, "/")
+
+	for k, v := range path {
+		elements[k+1] = strings.Trim(v, "/")
+	}
+
+	return strings.Join(elements, "/"), nil
+}
diff --git a/pkg/region/region_constants.go b/pkg/region/region_constants.go
new file mode 100644
index 0000000..ff78d83
--- /dev/null
+++ b/pkg/region/region_constants.go
@@ -0,0 +1,62 @@
+package region
+
+import (
+	"strings"
+)
+
+const (
+	// US represents New Relic's US-based production deployment.
+	US Name = "US"
+
+	// EU represents New Relic's EU-based production deployment.
+	EU Name = "EU"
+
+	// Staging represents New Relic's US-based staging deployment.
+	// This is for internal New Relic use only.
+	Staging Name = "Staging"
+)
+
+var Regions = map[Name]*Region{
+	US: {
+		name:                  "US",
+		infrastructureBaseURL: "https://infra-api.newrelic.com/v2",
+		nerdGraphBaseURL:      "https://api.newrelic.com/graphql",
+		restBaseURL:           "https://api.newrelic.com/v2",
+		syntheticsBaseURL:     "https://synthetics.newrelic.com/synthetics/api",
+	},
+	EU: {
+		name:                  "EU",
+		infrastructureBaseURL: "https://infra-api.eu.newrelic.com/v2",
+		nerdGraphBaseURL:      "https://api.eu.newrelic.com/graphql",
+		restBaseURL:           "https://api.eu.newrelic.com/v2",
+		syntheticsBaseURL:     "https://synthetics.eu.newrelic.com/synthetics/api",
+	},
+	Staging: {
+		name:                  "Staging",
+		infrastructureBaseURL: "https://staging-infra-api.newrelic.com/v2",
+		nerdGraphBaseURL:      "https://staging-api.newrelic.com/graphql",
+		restBaseURL:           "https://staging-api.newrelic.com/v2",
+		syntheticsBaseURL:     "https://staging-synthetics.newrelic.com/synthetics/api",
+	},
+}
+
+// Default represents the region returned if nothing was specified
+var Default *Region = Regions[US]
+
+// Parse takes a Region string and returns a RegionType
+func Parse(r string) *Region {
+	var ret Region
+
+	switch strings.ToLower(r) {
+	case "us":
+		ret = *Regions[US]
+	case "eu":
+		ret = *Regions[EU]
+	case "staging":
+		ret = *Regions[Staging]
+	default:
+		ret = *Default
+	}
+
+	return &ret
+}
diff --git a/pkg/synthetics/monitor_labels.go b/pkg/synthetics/monitor_labels.go
index f0ad7e5..cf88430 100644
--- a/pkg/synthetics/monitor_labels.go
+++ b/pkg/synthetics/monitor_labels.go
@@ -18,7 +18,7 @@ func (s *Synthetics) GetMonitorLabels(monitorID string) ([]*MonitorLabel, error)
 
 	resp := getMonitorLabelsResponse{}
 
-	_, err := s.client.Get(url, nil, &resp)
+	_, err := s.client.Get(s.config.Region().SyntheticsURL(url), nil, &resp)
 	if err != nil {
 		return []*MonitorLabel{}, err
 	}
@@ -34,7 +34,7 @@ func (s *Synthetics) AddMonitorLabel(monitorID, labelKey, labelValue string) err
 
 	// We use RawPost here due to the Syntheics API's lack of support for JSON on
 	// this call.  The values must be POSTed as bare key:value word string.
-	_, err := s.client.RawPost(url, nil, data, nil)
+	_, err := s.client.RawPost(s.config.Region().SyntheticsURL(url), nil, data, nil)
 	if err != nil {
 		return err
 	}
@@ -46,7 +46,7 @@ func (s *Synthetics) AddMonitorLabel(monitorID, labelKey, labelValue string) err
 func (s *Synthetics) DeleteMonitorLabel(monitorID, labelKey, labelValue string) error {
 	url := fmt.Sprintf("/v4/monitors/%s/labels/%s:%s", monitorID, strings.Title(labelKey), strings.Title(labelValue))
 
-	_, err := s.client.Delete(url, nil, nil)
+	_, err := s.client.Delete(s.config.Region().SyntheticsURL(url), nil, nil)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/synthetics/monitor_scripts.go b/pkg/synthetics/monitor_scripts.go
index cea6e64..c8559c3 100644
--- a/pkg/synthetics/monitor_scripts.go
+++ b/pkg/synthetics/monitor_scripts.go
@@ -10,7 +10,7 @@ import (
 func (s *Synthetics) GetMonitorScript(monitorID string) (*MonitorScript, error) {
 	resp := MonitorScript{}
 	url := fmt.Sprintf("/v4/monitors/%s/script", monitorID)
-	_, err := s.client.Get(url, nil, &resp)
+	_, err := s.client.Get(s.config.Region().SyntheticsURL(url), nil, &resp)
 
 	if err != nil {
 		return nil, err
@@ -31,8 +31,7 @@ func (s *Synthetics) GetMonitorScript(monitorID string) (*MonitorScript, error)
 func (s *Synthetics) UpdateMonitorScript(monitorID string, script MonitorScript) (*MonitorScript, error) {
 	script.Text = base64.StdEncoding.EncodeToString([]byte(script.Text))
 
-	url := fmt.Sprintf("/v4/monitors/%s/script", monitorID)
-	_, err := s.client.Put(url, nil, &script, nil)
+	_, err := s.client.Put(s.config.Region().SyntheticsURL("/v4/monitors", monitorID, "/script"), nil, &script, nil)
 
 	if err != nil {
 		return nil, err
diff --git a/pkg/synthetics/monitors.go b/pkg/synthetics/monitors.go
index 7b079ef..9253c8e 100644
--- a/pkg/synthetics/monitors.go
+++ b/pkg/synthetics/monitors.go
@@ -1,7 +1,6 @@
 package synthetics
 
 import (
-	"fmt"
 	"path"
 )
 
@@ -85,7 +84,7 @@ func (s *Synthetics) ListMonitors() ([]*Monitor, error) {
 		Limit: listMonitorsLimit,
 	}
 
-	_, err := s.client.Get("/v4/monitors", &queryParams, &resp)
+	_, err := s.client.Get(s.config.Region().SyntheticsURL("/v4/monitors"), &queryParams, &resp)
 
 	if err != nil {
 		return nil, err
@@ -97,8 +96,8 @@ func (s *Synthetics) ListMonitors() ([]*Monitor, error) {
 // GetMonitor is used to retrieve a specific New Relic Synthetics monitor.
 func (s *Synthetics) GetMonitor(monitorID string) (*Monitor, error) {
 	resp := Monitor{}
-	url := fmt.Sprintf("/v4/monitors/%s", monitorID)
-	_, err := s.client.Get(url, nil, &resp)
+
+	_, err := s.client.Get(s.config.Region().SyntheticsURL("/v4/monitors", monitorID), nil, &resp)
 
 	if err != nil {
 		return nil, err
@@ -109,7 +108,7 @@ func (s *Synthetics) GetMonitor(monitorID string) (*Monitor, error) {
 
 // CreateMonitor is used to create a New Relic Synthetics monitor.
 func (s *Synthetics) CreateMonitor(monitor Monitor) (*Monitor, error) {
-	resp, err := s.client.Post("/v4/monitors", nil, &monitor, nil)
+	resp, err := s.client.Post(s.config.Region().SyntheticsURL("/v4/monitors"), nil, &monitor, nil)
 
 	if err != nil {
 		return nil, err
@@ -125,8 +124,7 @@ func (s *Synthetics) CreateMonitor(monitor Monitor) (*Monitor, error) {
 
 // UpdateMonitor is used to update a New Relic Synthetics monitor.
 func (s *Synthetics) UpdateMonitor(monitor Monitor) (*Monitor, error) {
-	url := fmt.Sprintf("/v4/monitors/%s", monitor.ID)
-	_, err := s.client.Put(url, nil, &monitor, nil)
+	_, err := s.client.Put(s.config.Region().SyntheticsURL("/v4/monitors", monitor.ID), nil, &monitor, nil)
 
 	if err != nil {
 		return nil, err
@@ -137,8 +135,7 @@ func (s *Synthetics) UpdateMonitor(monitor Monitor) (*Monitor, error) {
 
 // DeleteMonitor is used to delete a New Relic Synthetics monitor.
 func (s *Synthetics) DeleteMonitor(monitorID string) error {
-	url := fmt.Sprintf("/v4/monitors/%s", monitorID)
-	_, err := s.client.Delete(url, nil, nil)
+	_, err := s.client.Delete(s.config.Region().SyntheticsURL("/v4/monitors", monitorID), nil, nil)
 
 	if err != nil {
 		return err
diff --git a/pkg/synthetics/secure_credentials.go b/pkg/synthetics/secure_credentials.go
index b55db75..c42c88c 100644
--- a/pkg/synthetics/secure_credentials.go
+++ b/pkg/synthetics/secure_credentials.go
@@ -1,9 +1,5 @@
 package synthetics
 
-import (
-	"fmt"
-)
-
 // SecureCredential represents a Synthetics secure credential.
 type SecureCredential struct {
 	Key         string `json:"key"`
@@ -15,10 +11,9 @@ type SecureCredential struct {
 
 // GetSecureCredentials is used to retrieve all secure credentials from your New Relic account.
 func (s *Synthetics) GetSecureCredentials() ([]*SecureCredential, error) {
-	url := "/v1/secure-credentials"
 	resp := getSecureCredentialsResponse{}
 
-	_, err := s.client.Get(url, nil, &resp)
+	_, err := s.client.Get(s.config.Region().SyntheticsURL("/v1/secure-credentials"), nil, &resp)
 	if err != nil {
 		return nil, err
 	}
@@ -28,10 +23,9 @@ func (s *Synthetics) GetSecureCredentials() ([]*SecureCredential, error) {
 
 // GetSecureCredential is used to retrieve a specific secure credential from your New Relic account.
 func (s *Synthetics) GetSecureCredential(key string) (*SecureCredential, error) {
-	url := fmt.Sprintf("/v1/secure-credentials/%s", key)
 	var sc SecureCredential
 
-	_, err := s.client.Get(url, nil, &sc)
+	_, err := s.client.Get(s.config.Region().SyntheticsURL("/v1/secure-credentials", key), nil, &sc)
 	if err != nil {
 		return nil, err
 	}
@@ -41,14 +35,13 @@ func (s *Synthetics) GetSecureCredential(key string) (*SecureCredential, error)
 
 // AddSecureCredential is used to add a secure credential to your New Relic account.
 func (s *Synthetics) AddSecureCredential(key, value, description string) (*SecureCredential, error) {
-	url := "/v1/secure-credentials"
 	sc := &SecureCredential{
 		Key:         key,
 		Value:       value,
 		Description: description,
 	}
 
-	_, err := s.client.Post(url, nil, sc, nil)
+	_, err := s.client.Post(s.config.Region().SyntheticsURL("/v1/secure-credentials"), nil, sc, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -58,14 +51,13 @@ func (s *Synthetics) AddSecureCredential(key, value, description string) (*Secur
 
 // UpdateSecureCredential is used to update a secure credential in your New Relic account.
 func (s *Synthetics) UpdateSecureCredential(key, value, description string) (*SecureCredential, error) {
-	url := fmt.Sprintf("/v1/secure-credentials/%s", key)
 	sc := &SecureCredential{
 		Key:         key,
 		Value:       value,
 		Description: description,
 	}
 
-	_, err := s.client.Put(url, nil, sc, nil)
+	_, err := s.client.Put(s.config.Region().SyntheticsURL("/v1/secure-credentials", key), nil, sc, nil)
 
 	if err != nil {
 		return nil, err
@@ -76,9 +68,7 @@ func (s *Synthetics) UpdateSecureCredential(key, value, description string) (*Se
 
 // DeleteSecureCredential deletes a secure credential from your New Relic account.
 func (s *Synthetics) DeleteSecureCredential(key string) error {
-	url := fmt.Sprintf("/v1/secure-credentials/%s", key)
-
-	_, err := s.client.Delete(url, nil, nil)
+	_, err := s.client.Delete(s.config.Region().SyntheticsURL("/v1/secure-credentials", key), nil, nil)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/synthetics/synthetics.go b/pkg/synthetics/synthetics.go
index ca4d821..669f128 100644
--- a/pkg/synthetics/synthetics.go
+++ b/pkg/synthetics/synthetics.go
@@ -6,20 +6,13 @@ import (
 
 	"github.com/newrelic/newrelic-client-go/internal/http"
 	"github.com/newrelic/newrelic-client-go/internal/logging"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
-// BaseURLs represents the base API URLs for the different environments of the Synthetics API.
-var BaseURLs = map[region.Region]string{
-	region.US:      "https://synthetics.newrelic.com/synthetics/api",
-	region.EU:      "https://synthetics.eu.newrelic.com/synthetics/api",
-	region.Staging: "https://staging-synthetics.newrelic.com/synthetics/api",
-}
-
 // Synthetics is used to communicate with the New Relic Synthetics product.
 type Synthetics struct {
 	client http.Client
+	config config.Config
 	logger logging.Logger
 	pager  http.Pager
 }
@@ -64,18 +57,12 @@ func (e *ErrorResponse) New() http.ErrorResponse {
 
 // New is used to create a new Synthetics client instance.
 func New(config config.Config) Synthetics {
-
-	if config.SyntheticsBaseURL == "" {
-		config.SyntheticsBaseURL = BaseURLs[region.Parse(string(config.Region))]
-	}
-
-	config.BaseURL = config.SyntheticsBaseURL
-
 	client := http.NewClient(config)
 	client.SetErrorValue(&ErrorResponse{})
 
 	pkg := Synthetics{
 		client: client,
+		config: config,
 		logger: config.GetLogger(),
 		pager:  &http.LinkHeaderPager{},
 	}
diff --git a/pkg/workloads/workloads.go b/pkg/workloads/workloads.go
index 7b643b3..451142a 100644
--- a/pkg/workloads/workloads.go
+++ b/pkg/workloads/workloads.go
@@ -5,7 +5,6 @@ package workloads
 import (
 	"github.com/newrelic/newrelic-client-go/internal/http"
 	"github.com/newrelic/newrelic-client-go/internal/logging"
-	"github.com/newrelic/newrelic-client-go/internal/region"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
@@ -22,6 +21,3 @@ func New(config config.Config) Workloads {
 		logger: config.GetLogger(),
 	}
 }
-
-// BaseURLs represents the base API URLs for the different environments of the New Relic NerdGraph API.
-var BaseURLs = region.NerdGraphBaseURLs


Test patch:
diff --git a/internal/http/client_test.go b/internal/http/client_test.go
index 8098358..2ed372f 100644
--- a/internal/http/client_test.go
+++ b/internal/http/client_test.go
@@ -11,7 +11,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 
-	"github.com/newrelic/newrelic-client-go/internal/region"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 	"github.com/newrelic/newrelic-client-go/pkg/config"
 	"github.com/newrelic/newrelic-client-go/pkg/errors"
 )
@@ -22,22 +22,22 @@ const (
 
 func TestConfig(t *testing.T) {
 	t.Parallel()
-	testBaseURL := "https://www.mocky.io"
+	testRestURL := "https://www.mocky.io"
 	testTimeout := time.Second * 5
 	testTransport := http.DefaultTransport
 
-	c := NewClient(config.Config{
-		PersonalAPIKey: testPersonalAPIKey,
-		BaseURL:        testBaseURL,
-		HTTPTransport:  testTransport,
-		ServiceName:    testServiceName,
-		Timeout:        &testTimeout,
-		UserAgent:      testUserAgent,
-	})
+	tc := config.New()
+	tc.HTTPTransport = testTransport
+	tc.Region().SetRestBaseURL(testRestURL)
+	tc.ServiceName = testServiceName
+	tc.Timeout = &testTimeout
+	tc.UserAgent = mock.UserAgent
+
+	c := NewClient(tc)
 
 	assert.Equal(t, &testTimeout, c.config.Timeout)
-	assert.Equal(t, testBaseURL, c.config.BaseURL)
-	assert.Equal(t, testUserAgent, c.config.UserAgent)
+	assert.Equal(t, testRestURL, c.config.Region().RestURL())
+	assert.Equal(t, mock.UserAgent, c.config.UserAgent)
 	assert.Equal(t, c.config.ServiceName, testServiceName+"|newrelic-client-go")
 
 	assert.Same(t, testTransport, c.config.HTTPTransport)
@@ -45,24 +45,24 @@ func TestConfig(t *testing.T) {
 
 func TestConfigDefaults(t *testing.T) {
 	t.Parallel()
-	c := NewClient(config.Config{
-		PersonalAPIKey: testPersonalAPIKey,
-	})
+	tc := mock.NewTestConfig(t, nil)
+	tc.ServiceName = testServiceName
+
+	c := NewClient(tc)
 
-	assert.Equal(t, region.DefaultBaseURLs[region.Parse(string(c.config.Region))], c.config.BaseURL)
-	assert.Contains(t, c.config.UserAgent, "newrelic/newrelic-client-go/")
-	assert.Equal(t, c.config.ServiceName, "newrelic-client-go")
+	assert.Contains(t, c.config.UserAgent, "newrelic/newrelic-client-go")
+	assert.Equal(t, c.config.ServiceName, testServiceName+"|newrelic-client-go")
 }
 
 func TestDefaultErrorValue(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusInternalServerError)
 		_, _ = w.Write([]byte(`{"error":{"title":"error message"}}`))
 	}))
 
-	_, err := c.Get("/path", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.Contains(t, err.(*errors.UnexpectedStatusCode).Error(), "error message")
 }
@@ -81,7 +81,7 @@ func (c *CustomErrorResponse) Error() string {
 
 func TestCustomErrorValue(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusInternalServerError)
 		_, _ = w.Write([]byte(`{"custom":"error message"}`))
@@ -89,7 +89,7 @@ func TestCustomErrorValue(t *testing.T) {
 
 	c.SetErrorValue(&CustomErrorResponse{})
 
-	_, err := c.Get("/path", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.Contains(t, err.(*errors.UnexpectedStatusCode).Error(), "error message")
 }
@@ -100,13 +100,13 @@ type CustomResponseValue struct {
 
 func TestResponseValue(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		_, _ = w.Write([]byte(`{"custom":"custom response string"}`))
 	}))
 
 	v := &CustomResponseValue{}
-	_, err := c.Get("/path", nil, v)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, v)
 
 	assert.NoError(t, err)
 	assert.Equal(t, &CustomResponseValue{Custom: "custom response string"}, v)
@@ -122,7 +122,7 @@ func TestQueryParams(t *testing.T) {
 		B: 2,
 	}
 
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusOK)
 
@@ -133,7 +133,7 @@ func TestQueryParams(t *testing.T) {
 		assert.Equal(t, "2", b)
 	}))
 
-	_, _ = c.Get("/path", &queryParams, nil)
+	_, _ = c.Get(c.config.Region().RestURL("path"), &queryParams, nil)
 }
 
 type TestRequestBody struct {
@@ -148,7 +148,7 @@ func TestRequestBodyMarshal(t *testing.T) {
 		B: "2",
 	}
 
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusOK)
 
@@ -159,7 +159,7 @@ func TestRequestBodyMarshal(t *testing.T) {
 		assert.Equal(t, &expected, actual)
 	}))
 
-	_, _ = c.Post("/path", nil, expected, nil)
+	_, _ = c.Post(c.config.Region().RestURL("path"), nil, expected, nil)
 }
 
 type TestInvalidRequestBody struct {
@@ -172,75 +172,47 @@ func TestRequestBodyMarshalError(t *testing.T) {
 		Channel: make(chan int),
 	}
 
-	c := NewTestAPIClient(nil)
+	c := NewTestAPIClient(t, nil)
 
-	_, err := c.Post("/path", nil, b, nil)
+	_, err := c.Post(c.config.Region().RestURL("/path"), nil, b, nil)
 	assert.Error(t, err)
 }
 
 func TestUrlParseError(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(nil)
+	c := NewTestAPIClient(t, nil)
 
-	_, err := c.Get("\\", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("\\"), nil, nil)
 	assert.Error(t, err)
 }
 
-func TestPathOnlyUrl(t *testing.T) {
-	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(http.StatusOK)
-
-		assert.Equal(t, r.URL, "https://www.mocky.io/v2/path")
-	}))
-
-	c.config.BaseURL = "https://www.mocky.io/v2"
-
-	_, _ = c.Get("/path", nil, nil)
-}
-
-func TestHostAndPathUrl(t *testing.T) {
-	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
-		w.WriteHeader(http.StatusOK)
-
-		assert.Equal(t, r.URL, "https:/www.httpbin.org/path")
-	}))
-
-	c.config.BaseURL = "https://www.mocky.io/v2"
-
-	_, _ = c.Get("https://www.httpbin.org/path", nil, nil)
-}
-
 type TestInvalidReponseBody struct {
 	Channel chan int `json:"channel"`
 }
 
 func TestResponseUnmarshalError(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		_, _ = w.Write([]byte(`{"channel": "test"}`))
 	}))
 
-	_, err := c.Get("/path", nil, &TestInvalidReponseBody{})
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, &TestInvalidReponseBody{})
 
 	assert.Error(t, err)
 }
 
 func TestHeaders(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusOK)
 
-		assert.Equal(t, testUserAgent, r.Header.Get("user-agent"))
+		assert.Equal(t, mock.UserAgent, r.Header.Get("user-agent"))
 		assert.Equal(t, "newrelic-client-go", r.Header.Get("newrelic-requesting-services"))
 	}))
 
-	_, err := c.Get("/path", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.Nil(t, err)
 }
@@ -256,15 +228,13 @@ func TestCustomClientHeaders(t *testing.T) {
 		assert.Equal(t, "custom-requesting-service|newrelic-client-go", r.Header.Get("newrelic-requesting-services"))
 	}))
 
-	c := NewClient(config.Config{
-		PersonalAPIKey: testPersonalAPIKey,
-		AdminAPIKey:    testAdminAPIKey,
-		BaseURL:        ts.URL,
-		UserAgent:      "custom-user-agent",
-		ServiceName:    "custom-requesting-service",
-	})
+	tc := mock.NewTestConfig(t, ts)
+	tc.UserAgent = "custom-user-agent"
+	tc.ServiceName = "custom-requesting-service"
 
-	_, err := c.Get("/path", nil, nil)
+	c := NewClient(tc)
+
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.Nil(t, err)
 }
@@ -280,13 +250,11 @@ func TestCustomRequestHeaders(t *testing.T) {
 		assert.Equal(t, "custom-requesting-service|newrelic-client-go", r.Header.Get("newrelic-requesting-services"))
 	}))
 
-	c := NewClient(config.Config{
-		PersonalAPIKey: testPersonalAPIKey,
-		AdminAPIKey:    testAdminAPIKey,
-		BaseURL:        ts.URL,
-	})
+	tc := mock.NewTestConfig(t, ts)
+
+	c := NewClient(tc)
 
-	req, err := NewRequest(c, "GET", "/path", nil, nil, nil)
+	req, err := NewRequest(c, "GET", c.config.Region().RestURL("path"), nil, nil, nil)
 
 	req.SetHeader("user-agent", "custom-user-agent")
 	req.SetServiceName("custom-requesting-service")
@@ -302,95 +270,92 @@ func TestAdminAPIKeyHeader(t *testing.T) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusOK)
 
-		assert.Equal(t, testAdminAPIKey, r.Header.Get("x-api-key"))
+		assert.Equal(t, mock.AdminAPIKey, r.Header.Get("x-api-key"))
 	}))
 
-	c := NewClient(config.Config{
-		AdminAPIKey: testAdminAPIKey,
-		BaseURL:     ts.URL,
-		UserAgent:   testUserAgent,
-	})
+	tc := mock.NewTestConfig(t, ts)
+	c := NewClient(tc)
 
-	_, err := c.Get("/path", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.Nil(t, err)
 }
 
 func TestErrNotFound(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusNotFound)
 	}))
 
-	_, err := c.Get("/path", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.IsType(t, &errors.NotFound{}, err)
 }
 
 func TestInternalServerError(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusInternalServerError)
 	}))
 
-	_, err := c.Get("/path", nil, nil)
+	_, err := c.Get(c.config.Region().RestURL("path"), nil, nil)
 
 	assert.IsType(t, &errors.UnexpectedStatusCode{}, err)
 }
 
 func TestPost(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusOK)
 		_, _ = w.Write([]byte(`{}`))
 	}))
 
-	_, err := c.Post("/path", &struct{}{}, &struct{}{}, &struct{}{})
+	_, err := c.Post(c.config.Region().RestURL("path"), &struct{}{}, &struct{}{}, &struct{}{})
 
 	assert.NoError(t, err)
 }
 
 func TestRawPost(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusOK)
 		_, _ = w.Write([]byte(`{}`))
 	}))
 
 	// string
-	_, err := c.RawPost("/path", &struct{}{}, "test string payload", &struct{}{})
+	_, err := c.RawPost(c.config.Region().RestURL("path"), &struct{}{}, "test string payload", &struct{}{})
 	assert.NoError(t, err)
 
 	// []byte
-	_, err = c.RawPost("/path", &struct{}{}, []byte(`bytes`), &struct{}{})
+	_, err = c.RawPost(c.config.Region().RestURL("path"), &struct{}{}, []byte(`bytes`), &struct{}{})
 	assert.NoError(t, err)
 
 	// invalid
-	_, err = c.RawPost("/path", &struct{}{}, &struct{}{}, &struct{}{})
+	_, err = c.RawPost(c.config.Region().RestURL("path"), &struct{}{}, &struct{}{}, &struct{}{})
 	assert.Error(t, err)
 }
 
 func TestPut(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusOK)
 		_, _ = w.Write([]byte(`{}`))
 	}))
 
-	_, err := c.Put("/path", &struct{}{}, &struct{}{}, &struct{}{})
+	_, err := c.Put(c.config.Region().RestURL("path"), &struct{}{}, &struct{}{}, &struct{}{})
 
 	assert.NoError(t, err)
 }
 
 func TestDelete(t *testing.T) {
 	t.Parallel()
-	c := NewTestAPIClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	c := NewTestAPIClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusOK)
 
 		_, _ = w.Write([]byte(`{}`))
 	}))
 
-	_, err := c.Delete("/path", &struct{}{}, &struct{}{})
+	_, err := c.Delete(c.config.Region().RestURL("path"), &struct{}{}, &struct{}{})
 
 	assert.NoError(t, err)
 }
diff --git a/internal/http/test_helpers.go b/internal/http/test_helpers.go
index 205b1a1..1c5104f 100644
--- a/internal/http/test_helpers.go
+++ b/internal/http/test_helpers.go
@@ -3,26 +3,15 @@ package http
 import (
 	"net/http"
 	"net/http/httptest"
+	"testing"
 
-	"github.com/newrelic/newrelic-client-go/pkg/config"
-)
-
-var (
-	testPersonalAPIKey = "apiKey"
-	testAdminAPIKey    = "adminAPIKey"
-	testUserAgent      = "userAgent"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 // NewTestAPIClient returns a test Client instance that is configured to communicate with a mock server.
-func NewTestAPIClient(handler http.Handler) Client {
+func NewTestAPIClient(t *testing.T, handler http.Handler) Client {
 	ts := httptest.NewServer(handler)
+	tc := mock.NewTestConfig(t, ts)
 
-	c := NewClient(config.Config{
-		PersonalAPIKey: testPersonalAPIKey,
-		AdminAPIKey:    testAdminAPIKey,
-		BaseURL:        ts.URL,
-		UserAgent:      testUserAgent,
-	})
-
-	return c
+	return NewClient(tc)
 }
diff --git a/internal/region/region_test.go b/internal/region/region_test.go
deleted file mode 100644
index 30d957b..0000000
--- a/internal/region/region_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// +build unit
-
-package region
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestParse(t *testing.T) {
-	t.Parallel()
-
-	pairs := map[string]Region{
-		"us":      US,
-		"Us":      US,
-		"uS":      US,
-		"US":      US,
-		"eu":      EU,
-		"Eu":      EU,
-		"eU":      EU,
-		"EU":      EU,
-		"staging": Staging,
-		"Staging": Staging,
-	}
-
-	for k, v := range pairs {
-		result := Parse(k)
-		assert.Equal(t, result, v)
-	}
-
-	// Default is US
-	result := Parse("")
-	assert.Equal(t, result, US)
-}
-
-func TestString(t *testing.T) {
-	t.Parallel()
-
-	pairs := map[Region]string{
-		US:      "US",
-		EU:      "EU",
-		Staging: "Staging",
-	}
-
-	for k, v := range pairs {
-		result := k.String()
-		assert.Equal(t, result, v)
-	}
-
-	// Verify that an uninitialized Region (should be 0) isn't known
-	var unk Region
-	result := unk.String()
-	assert.Equal(t, result, "(Unknown)")
-}
diff --git a/internal/testing/config.go b/internal/testing/config.go
new file mode 100644
index 0000000..0521bc2
--- /dev/null
+++ b/internal/testing/config.go
@@ -0,0 +1,68 @@
+package testing
+
+import (
+	"net/http/httptest"
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/newrelic/newrelic-client-go/pkg/config"
+	"github.com/newrelic/newrelic-client-go/pkg/region"
+)
+
+const (
+	AdminAPIKey    = "adminAPIKey"                                     // AdminAPIKey used in mock configs (from Environment for Integration tests)
+	LogLevel       = "debug"                                           // LogLevel used in mock configs
+	PersonalAPIKey = "personalAPIKey"                                  // PersonalAPIKey used in mock configs (from Environment for Integration tests)
+	UserAgent      = "newrelic/newrelic-client-go (automated testing)" // UserAgent used in mock configs
+)
+
+// NewTestConfig returns a fully saturated configration with modified BaseURLs
+// for all endpoints based on the test server passed in
+func NewTestConfig(t *testing.T, testServer *httptest.Server) config.Config {
+	cfg := config.New()
+
+	// Set some defaults from Testing constants
+	cfg.AdminAPIKey = AdminAPIKey
+	cfg.LogLevel = LogLevel
+	cfg.PersonalAPIKey = PersonalAPIKey
+	cfg.UserAgent = UserAgent
+
+	if testServer != nil {
+		cfg.Region().SetInfrastructureBaseURL(testServer.URL)
+		cfg.Region().SetNerdGraphBaseURL(testServer.URL)
+		cfg.Region().SetRestBaseURL(testServer.URL)
+		cfg.Region().SetSyntheticsBaseURL(testServer.URL)
+	}
+
+	return cfg
+}
+
+// NewIntegrationTestConfig grabs environment vars for required fields or skips the test.
+// returns a fully saturated configuration
+func NewIntegrationTestConfig(t *testing.T) config.Config {
+	envPersonalAPIKey := os.Getenv("NEW_RELIC_API_KEY")
+	envAdminAPIKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	envRegion := os.Getenv("NEW_RELIC_REGION")
+
+	if envPersonalAPIKey == "" && envAdminAPIKey == "" {
+		t.Skipf("acceptance testing requires NEW_RELIC_API_KEY and NEW_RELIC_ADMIN_API_KEY")
+	}
+
+	cfg := config.New()
+
+	// Set some defaults
+	cfg.LogLevel = LogLevel
+	cfg.UserAgent = UserAgent
+
+	cfg.PersonalAPIKey = envPersonalAPIKey
+	cfg.AdminAPIKey = envAdminAPIKey
+
+	if envRegion != "" {
+		err := cfg.SetRegion(region.Parse(envRegion))
+		assert.NoError(t, err)
+	}
+
+	return cfg
+}
diff --git a/newrelic/example_basic_test.go b/newrelic/example_basic_test.go
index a006a1f..d0b1133 100644
--- a/newrelic/example_basic_test.go
+++ b/newrelic/example_basic_test.go
@@ -7,10 +7,10 @@ import (
 
 	"github.com/newrelic/newrelic-client-go/pkg/alerts"
 	"github.com/newrelic/newrelic-client-go/pkg/apm"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
 	"github.com/newrelic/newrelic-client-go/pkg/dashboards"
 	"github.com/newrelic/newrelic-client-go/pkg/entities"
 	"github.com/newrelic/newrelic-client-go/pkg/plugins"
+	"github.com/newrelic/newrelic-client-go/pkg/region"
 )
 
 func Example_basic() {
@@ -18,7 +18,7 @@ func Example_basic() {
 	client, err := New(
 		ConfigAdminAPIKey(os.Getenv("NEW_RELIC_ADMIN_API_KEY")),
 		ConfigPersonalAPIKey(os.Getenv("NEW_RELIC_API_KEY")),
-		ConfigRegion(config.RegionTypes.US),
+		ConfigRegion(region.US),
 		ConfigLogLevel("DEBUG"),
 	)
 	if err != nil {
diff --git a/pkg/alerts/alerts_test.go b/pkg/alerts/alerts_test.go
index 381097a..91979f7 100644
--- a/pkg/alerts/alerts_test.go
+++ b/pkg/alerts/alerts_test.go
@@ -1,56 +1,32 @@
+// +build unit integration
+
 package alerts
 
 import (
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	mock "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
 // TODO: This is used by incidents_test.go still, need to refactor
-// nolint
-func newTestClient(handler http.Handler) Alerts {
+func newTestClient(t *testing.T, handler http.Handler) Alerts {
 	ts := httptest.NewServer(handler)
+	tc := mock.NewTestConfig(t, ts)
 
-	return New(config.Config{
-		AdminAPIKey:           "abc123",
-		BaseURL:               ts.URL,
-		InfrastructureBaseURL: ts.URL,
-		UserAgent:             "newrelic/newrelic-client-go",
-	})
+	return New(tc)
 }
 
-// nolint
-func newMockResponse(
-	t *testing.T,
-	mockJSONResponse string,
-	statusCode int,
-) Alerts {
+func newMockResponse(t *testing.T, mockJSONResponse string, statusCode int) Alerts {
 	ts := mock.NewMockServer(t, mockJSONResponse, statusCode)
+	tc := mock.NewTestConfig(t, ts)
 
-	return New(config.Config{
-		AdminAPIKey:           "abc123",
-		BaseURL:               ts.URL,
-		InfrastructureBaseURL: ts.URL,
-		UserAgent:             "newrelic/newrelic-client-go",
-	})
+	return New(tc)
 }
 
-// nolint
 func newIntegrationTestClient(t *testing.T) Alerts {
-	personalAPIKey := os.Getenv("NEW_RELIC_API_KEY")
-	adminAPIKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
-
-	if personalAPIKey == "" && adminAPIKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_API_KEY and NEW_RELIC_ADMIN_API_KEY")
-	}
-
-	return New(config.Config{
-		AdminAPIKey:    adminAPIKey,
-		PersonalAPIKey: personalAPIKey,
-		LogLevel:       "debug",
-	})
+	tc := mock.NewIntegrationTestConfig(t)
+
+	return New(tc)
 }
diff --git a/pkg/alerts/conditions_test.go b/pkg/alerts/conditions_test.go
index 0a2f6dd..0f9a325 100644
--- a/pkg/alerts/conditions_test.go
+++ b/pkg/alerts/conditions_test.go
@@ -1,3 +1,5 @@
+// +build unit
+
 package alerts
 
 import (
diff --git a/pkg/alerts/example_policy_test.go b/pkg/alerts/example_policy_test.go
index f043e23..9a955c2 100644
--- a/pkg/alerts/example_policy_test.go
+++ b/pkg/alerts/example_policy_test.go
@@ -10,10 +10,9 @@ import (
 func Example_policy() {
 	// Initialize the client configuration.  A Personal API key or Admin API key
 	// is required to communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey:    os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/alerts/incidents_test.go b/pkg/alerts/incidents_test.go
index 805a5d1..bc06846 100644
--- a/pkg/alerts/incidents_test.go
+++ b/pkg/alerts/incidents_test.go
@@ -81,7 +81,7 @@ var failingTestHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Re
 func TestListIncidents(t *testing.T) {
 	t.Parallel()
 
-	c := newTestClient(incidentTestAPIHandler)
+	c := newTestClient(t, incidentTestAPIHandler)
 
 	expected := []*Incident{
 		{
@@ -115,7 +115,7 @@ func TestListIncidents(t *testing.T) {
 func TestOpenListIncidents(t *testing.T) {
 	t.Parallel()
 
-	c := newTestClient(incidentTestAPIHandler)
+	c := newTestClient(t, incidentTestAPIHandler)
 
 	expected := []*Incident{
 		{
@@ -139,7 +139,7 @@ func TestOpenListIncidents(t *testing.T) {
 func TestListIncidentsWithoutViolations(t *testing.T) {
 	t.Parallel()
 
-	c := newTestClient(incidentTestAPIHandler)
+	c := newTestClient(t, incidentTestAPIHandler)
 
 	expected := []*Incident{
 		{
@@ -171,7 +171,7 @@ func TestListIncidentsWithoutViolations(t *testing.T) {
 func TestListIncidentFailing(t *testing.T) {
 	t.Parallel()
 
-	c := newTestClient(failingTestHandler)
+	c := newTestClient(t, failingTestHandler)
 
 	_, err := c.ListIncidents(false, false)
 
@@ -208,7 +208,7 @@ func TestAcknowledgeIncident(t *testing.T) {
 func TestAcknowledgeIncidentFailing(t *testing.T) {
 	t.Parallel()
 
-	c := newTestClient(failingTestHandler)
+	c := newTestClient(t, failingTestHandler)
 
 	_, err := c.CloseIncident(42)
 
@@ -249,7 +249,7 @@ func TestCloseIncident(t *testing.T) {
 func TestCloseIncidentFailing(t *testing.T) {
 	t.Parallel()
 
-	c := newTestClient(failingTestHandler)
+	c := newTestClient(t, failingTestHandler)
 
 	_, err := c.CloseIncident(42)
 	if err == nil {
diff --git a/pkg/alerts/multi_location_synthetics_conditions_test.go b/pkg/alerts/multi_location_synthetics_conditions_test.go
index e5f7a1c..896cb41 100644
--- a/pkg/alerts/multi_location_synthetics_conditions_test.go
+++ b/pkg/alerts/multi_location_synthetics_conditions_test.go
@@ -1,3 +1,5 @@
+// +build unit
+
 package alerts
 
 import (
diff --git a/pkg/alerts/policies_test.go b/pkg/alerts/policies_test.go
index 4c594dc..b714677 100644
--- a/pkg/alerts/policies_test.go
+++ b/pkg/alerts/policies_test.go
@@ -106,7 +106,7 @@ func TestListPoliciesWithParams(t *testing.T) {
 	t.Parallel()
 	expectedName := "does-not-exist"
 
-	alerts := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	alerts := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 
 		name := values.Get("filter[name]")
diff --git a/pkg/alerts/synthetics_conditions_integration_test.go b/pkg/alerts/synthetics_conditions_integration_test.go
index b6ee82c..c24a67e 100644
--- a/pkg/alerts/synthetics_conditions_integration_test.go
+++ b/pkg/alerts/synthetics_conditions_integration_test.go
@@ -4,21 +4,21 @@ package alerts
 
 import (
 	"fmt"
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	nr "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 	"github.com/newrelic/newrelic-client-go/pkg/synthetics"
 )
 
 func TestIntegrationSyntheticsConditions(t *testing.T) {
 	t.Parallel()
 
+	tc := mock.NewIntegrationTestConfig(t)
+
 	var (
-		testRandStr                      = nr.RandSeq(5)
+		testRandStr                      = mock.RandSeq(5)
 		testIntegrationSyntheticsMonitor = synthetics.Monitor{
 			Name:         fmt.Sprintf("test-synthetics-alert-conditions-monitor-%s", testRandStr),
 			Type:         synthetics.MonitorTypes.Ping,
@@ -39,9 +39,7 @@ func TestIntegrationSyntheticsConditions(t *testing.T) {
 	)
 
 	alerts := newIntegrationTestClient(t)
-	synth := synthetics.New(config.Config{
-		AdminAPIKey: os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-	})
+	synth := synthetics.New(tc)
 
 	// Setup
 	monitor, err := synth.CreateMonitor(testIntegrationSyntheticsMonitor)
diff --git a/pkg/apm/apm_test.go b/pkg/apm/apm_test.go
index 9dd2fef..0deaada 100644
--- a/pkg/apm/apm_test.go
+++ b/pkg/apm/apm_test.go
@@ -3,56 +3,33 @@ package apm
 import (
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	mock "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
 // nolint
-func newTestClient(handler http.Handler) APM {
+func newTestClient(t *testing.T, handler http.Handler) APM {
 	ts := httptest.NewServer(handler)
+	tc := mock.NewTestConfig(t, ts)
 
-	c := New(config.Config{
-		PersonalAPIKey: "abc123",
-		BaseURL:        ts.URL,
-		UserAgent:      "newrelic/newrelic-client-go",
-		LogLevel:       "debug",
-	})
+	c := New(tc)
 
 	return c
 }
 
 // nolint
-func newMockResponse(
-	t *testing.T,
-	mockJSONResponse string,
-	statusCode int,
-) APM {
+func newMockResponse(t *testing.T, mockJSONResponse string, statusCode int) APM {
 	ts := mock.NewMockServer(t, mockJSONResponse, statusCode)
+	tc := mock.NewTestConfig(t, ts)
 
-	return New(config.Config{
-		PersonalAPIKey: "abc123",
-		BaseURL:        ts.URL,
-		UserAgent:      "newrelic/newrelic-client-go",
-	})
+	return New(tc)
 }
 
 // nolint
 func newIntegrationTestClient(t *testing.T) APM {
-	personalAPIKey := os.Getenv("NEW_RELIC_API_KEY")
-	adminAPIKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
-
-	if personalAPIKey == "" && adminAPIKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_API_KEY and NEW_RELIC_ADMIN_API_KEY")
-	}
-
-	client := New(config.Config{
-		AdminAPIKey:    adminAPIKey,
-		PersonalAPIKey: personalAPIKey,
-		LogLevel:       "debug",
-	})
+	cfg := mock.NewIntegrationTestConfig(t)
+	client := New(cfg)
 
 	return client
 }
diff --git a/pkg/apm/applications_test.go b/pkg/apm/applications_test.go
index b06bf4f..95d63cd 100644
--- a/pkg/apm/applications_test.go
+++ b/pkg/apm/applications_test.go
@@ -203,7 +203,7 @@ func TestListApplicationsWithParams(t *testing.T) {
 	expectedLanguage := "appLanguage"
 	expectedIDs := "123,456"
 
-	apm := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	apm := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 
 		name := values.Get("filter[name]")
diff --git a/pkg/apm/example_application_test.go b/pkg/apm/example_application_test.go
index eb4b4b6..4d0a32e 100644
--- a/pkg/apm/example_application_test.go
+++ b/pkg/apm/example_application_test.go
@@ -10,10 +10,9 @@ import (
 func Example_application() {
 	// Initialize the client configuration.  A Personal API key or Admin API key
 	// is required to communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey:    os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/apm/example_key_transaction_test.go b/pkg/apm/example_key_transaction_test.go
index a88c9f0..26a77e5 100644
--- a/pkg/apm/example_key_transaction_test.go
+++ b/pkg/apm/example_key_transaction_test.go
@@ -11,10 +11,9 @@ import (
 func Example_keyTransaction() {
 	// Initialize the client configuration.  A Personal API key or Admin API key
 	// is required to communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey:    os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/apm/example_labels_test.go b/pkg/apm/example_labels_test.go
index 603271d..8e10d55 100644
--- a/pkg/apm/example_labels_test.go
+++ b/pkg/apm/example_labels_test.go
@@ -11,10 +11,9 @@ import (
 func Example_labels() {
 	// Initialize the client configuration.  A Personal API key or Admin API key
 	// is required to communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey:    os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/apm/key_transactions_test.go b/pkg/apm/key_transactions_test.go
index eb373c9..f1fe881 100644
--- a/pkg/apm/key_transactions_test.go
+++ b/pkg/apm/key_transactions_test.go
@@ -116,7 +116,7 @@ func TestListKeyTransactionsWithParams(t *testing.T) {
 	keyTransactionName := "test-key-transaction"
 	idsFilter := "123,456,789"
 
-	apm := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	apm := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 		name := values.Get("filter[name]")
 
diff --git a/pkg/dashboards/dashboard_integration_test.go b/pkg/dashboards/dashboard_integration_test.go
index 62ec1b3..841f5d3 100644
--- a/pkg/dashboards/dashboard_integration_test.go
+++ b/pkg/dashboards/dashboard_integration_test.go
@@ -3,27 +3,19 @@
 package dashboards
 
 import (
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 func TestIntegrationDashboards(t *testing.T) {
 	t.Parallel()
 
-	apiKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	tc := mock.NewIntegrationTestConfig(t)
 
-	if apiKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_ADMIN_API_KEY to be set")
-	}
-
-	dashboards := New(config.Config{
-		AdminAPIKey: apiKey,
-		LogLevel:    "debug",
-	})
+	dashboards := New(tc)
 
 	d := Dashboard{
 		Metadata: DashboardMetadata{
diff --git a/pkg/dashboards/dashboards_test.go b/pkg/dashboards/dashboards_test.go
index 8019c68..9c3034a 100644
--- a/pkg/dashboards/dashboards_test.go
+++ b/pkg/dashboards/dashboards_test.go
@@ -13,32 +13,20 @@ import (
 	"github.com/stretchr/testify/assert"
 
 	mock "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
-func newTestClient(handler http.Handler) Dashboards {
+func newTestClient(t *testing.T, handler http.Handler) Dashboards {
 	ts := httptest.NewServer(handler)
+	tc := mock.NewTestConfig(t, ts)
 
-	return New(config.Config{
-		AdminAPIKey: "abc123",
-		BaseURL:     ts.URL,
-		UserAgent:   "newrelic/newrelic-client-go",
-		LogLevel:    "debug",
-	})
+	return New(tc)
 }
 
-func newMockResponse(
-	t *testing.T,
-	mockJSONResponse string,
-	statusCode int,
-) Dashboards {
+func newMockResponse(t *testing.T, mockJSONResponse string, statusCode int) Dashboards {
 	ts := mock.NewMockServer(t, mockJSONResponse, statusCode)
+	tc := mock.NewTestConfig(t, ts)
 
-	return New(config.Config{
-		AdminAPIKey: "abc123",
-		BaseURL:     ts.URL,
-		UserAgent:   "newrelic/newrelic-client-go",
-	})
+	return New(tc)
 }
 
 var (
@@ -323,7 +311,7 @@ func TestListDashboardsWithParams(t *testing.T) {
 	expectedSort := "sort"
 	expectedTitle := "title"
 
-	dashboards := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	dashboards := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 
 		assert.Equal(t, expectedCategory, values.Get("filter[category]"))
diff --git a/pkg/dashboards/example_dashboard_test.go b/pkg/dashboards/example_dashboard_test.go
index f32fc45..5398d7e 100644
--- a/pkg/dashboards/example_dashboard_test.go
+++ b/pkg/dashboards/example_dashboard_test.go
@@ -11,9 +11,8 @@ import (
 func Example_dashboard() {
 	// Initialize the client configuration.  An Admin API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey: os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/entities/entity_integration_test.go b/pkg/entities/entity_integration_test.go
index 68efb94..3f97025 100644
--- a/pkg/entities/entity_integration_test.go
+++ b/pkg/entities/entity_integration_test.go
@@ -3,13 +3,12 @@
 package entities
 
 import (
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 func TestIntegrationSearchEntities(t *testing.T) {
@@ -104,17 +103,8 @@ func TestIntegrationGetEntity_ApmEntityOutline(t *testing.T) {
 
 }
 
-// nolint
 func newIntegrationTestClient(t *testing.T) Entities {
-	apiKey := os.Getenv("NEW_RELIC_API_KEY")
+	tc := mock.NewIntegrationTestConfig(t)
 
-	if apiKey == "" {
-		t.Skipf("acceptance testing for graphql requires your personal API key")
-	}
-
-	return New(config.Config{
-		PersonalAPIKey: apiKey,
-		UserAgent:      "newrelic/newrelic-client-go",
-		LogLevel:       "debug",
-	})
+	return New(tc)
 }
diff --git a/pkg/entities/example_entity_test.go b/pkg/entities/example_entity_test.go
index 26962ce..239dc84 100644
--- a/pkg/entities/example_entity_test.go
+++ b/pkg/entities/example_entity_test.go
@@ -11,9 +11,8 @@ import (
 func Example_entity() {
 	// Initialize the client configuration.  A Personal API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/entities/example_tags_test.go b/pkg/entities/example_tags_test.go
index effe087..0d8b087 100644
--- a/pkg/entities/example_tags_test.go
+++ b/pkg/entities/example_tags_test.go
@@ -11,9 +11,8 @@ import (
 func Example_tags() {
 	// Initialize the client configuration.  A Personal API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/infrastructure/infrastructure_test.go b/pkg/infrastructure/infrastructure_test.go
index 3201de4..dd8634e 100644
--- a/pkg/infrastructure/infrastructure_test.go
+++ b/pkg/infrastructure/infrastructure_test.go
@@ -1,25 +1,3 @@
 // +build unit
 
 package infrastructure
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/newrelic/newrelic-client-go/internal/region"
-)
-
-func TestBaseURLs(t *testing.T) {
-	t.Parallel()
-
-	pairs := map[region.Region]string{
-		region.US:      "https://infra-api.newrelic.com/v2",
-		region.EU:      "https://infra-api.eu.newrelic.com/v2",
-		region.Staging: "https://staging-infra-api.newrelic.com/v2",
-	}
-
-	for k, v := range pairs {
-		assert.Equal(t, v, BaseURLs[k])
-	}
-}
diff --git a/pkg/nerdgraph/example_query_test.go b/pkg/nerdgraph/example_query_test.go
index 5436a04..0cf0c7c 100644
--- a/pkg/nerdgraph/example_query_test.go
+++ b/pkg/nerdgraph/example_query_test.go
@@ -11,9 +11,8 @@ import (
 func Example_query() {
 	// Initialize the client configuration.  A Personal API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/nerdgraph/nerdgraph_integration_test.go b/pkg/nerdgraph/nerdgraph_integration_test.go
index f5214fb..27768d3 100644
--- a/pkg/nerdgraph/nerdgraph_integration_test.go
+++ b/pkg/nerdgraph/nerdgraph_integration_test.go
@@ -3,12 +3,11 @@
 package nerdgraph
 
 import (
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 func TestIntegrationQuery(t *testing.T) {
@@ -64,14 +63,7 @@ func TestIntegrationQueryWithVariables(t *testing.T) {
 
 // nolint
 func newNerdGraphIntegrationTestClient(t *testing.T) NerdGraph {
-	apiKey := os.Getenv("NEW_RELIC_API_KEY")
+	tc := mock.NewIntegrationTestConfig(t)
 
-	if apiKey == "" {
-		t.Skipf("acceptance testing for NerdGraph requires NEW_RELIC_API_KEY to be set")
-	}
-
-	return New(config.Config{
-		PersonalAPIKey: apiKey,
-		UserAgent:      "newrelic/newrelic-client-go",
-	})
+	return New(tc)
 }
diff --git a/pkg/plugins/components_integration_test.go b/pkg/plugins/components_integration_test.go
index 672cd71..6a42048 100644
--- a/pkg/plugins/components_integration_test.go
+++ b/pkg/plugins/components_integration_test.go
@@ -3,28 +3,19 @@
 package plugins
 
 import (
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 func TestIntegrationComponents(t *testing.T) {
 	t.Parallel()
 
-	apiKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
-
-	if apiKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_ADMIN_API_KEY to be set")
-	}
-
-	api := New(config.Config{
-		AdminAPIKey: apiKey,
-		LogLevel:    "debug",
-	})
+	tc := mock.NewIntegrationTestConfig(t)
 
+	api := New(tc)
 	a, err := api.ListComponents(nil)
 
 	require.NoError(t, err)
diff --git a/pkg/plugins/components_test.go b/pkg/plugins/components_test.go
index 7d0e043..fcb250d 100644
--- a/pkg/plugins/components_test.go
+++ b/pkg/plugins/components_test.go
@@ -132,7 +132,7 @@ func TestListComponentsWithParams(t *testing.T) {
 	expectedPluginID := "1234"
 	expectedHealthStatus := "true"
 
-	plugins := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	plugins := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 
 		name := values.Get("filter[name]")
@@ -224,7 +224,7 @@ func TestGetComponentMetricDataWithParams(t *testing.T) {
 	expectedSummarize := "true"
 	expectedRaw := "true"
 
-	plugins := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	plugins := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 
 		names := values.Get("names[]")
diff --git a/pkg/plugins/plugins_test.go b/pkg/plugins/plugins_test.go
index 9d6a8a4..e24b95c 100644
--- a/pkg/plugins/plugins_test.go
+++ b/pkg/plugins/plugins_test.go
@@ -4,61 +4,35 @@ import (
 	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
 	mock "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
 )
 
 // nolint
-func newTestClient(handler http.Handler) Plugins {
+func newTestClient(t *testing.T, handler http.Handler) Plugins {
 	ts := httptest.NewServer(handler)
+	tc := mock.NewTestConfig(t, ts)
 
-	c := New(config.Config{
-		PersonalAPIKey: "abc123",
-		BaseURL:        ts.URL,
-		UserAgent:      "newrelic/newrelic-client-go",
-		LogLevel:       "debug",
-	})
-
-	return c
+	return New(tc)
 }
 
 // nolint
-func newMockResponse(
-	t *testing.T,
-	mockJSONResponse string,
-	statusCode int,
-) Plugins {
+func newMockResponse(t *testing.T, mockJSONResponse string, statusCode int) Plugins {
 	ts := mock.NewMockServer(t, mockJSONResponse, statusCode)
+	tc := mock.NewTestConfig(t, ts)
 
-	return New(config.Config{
-		PersonalAPIKey: "abc123",
-		BaseURL:        ts.URL,
-		UserAgent:      "newrelic/newrelic-client-go",
-	})
+	return New(tc)
 }
 
 // nolint
 func newIntegrationTestClient(t *testing.T) Plugins {
-	personalAPIKey := os.Getenv("NEW_RELIC_API_KEY")
-	adminAPIKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
-
-	if personalAPIKey == "" && adminAPIKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_API_KEY and NEW_RELIC_ADMIN_API_KEY")
-	}
-
-	client := New(config.Config{
-		PersonalAPIKey: personalAPIKey,
-		AdminAPIKey:    adminAPIKey,
-		LogLevel:       "debug",
-	})
+	tc := mock.NewIntegrationTestConfig(t)
 
-	return client
+	return New(tc)
 }
 
 var (
@@ -198,7 +172,7 @@ func TestListPluginsWithParams(t *testing.T) {
 	guidFilter := "net.jondoe.newrelic_redis_plugin"
 	idsFilter := "999"
 
-	plugins := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	plugins := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		values := r.URL.Query()
 
 		guid := values.Get("filter[guid]")
@@ -233,7 +207,7 @@ func TestListPluginsWithDetailedParam(t *testing.T) {
 	t.Parallel()
 	expectedDetailed := "true"
 
-	plugins := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	plugins := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		guid := r.URL.Query().Get("detailed")
 		require.Equal(t, expectedDetailed, guid)
 
@@ -277,7 +251,7 @@ func TestGetPluginWithParams(t *testing.T) {
 	t.Parallel()
 	expectedDetailed := "true"
 
-	plugins := newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	plugins := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		detailed := r.URL.Query().Get("detailed")
 		require.Equal(t, expectedDetailed, detailed)
 
diff --git a/pkg/region/region_test.go b/pkg/region/region_test.go
new file mode 100644
index 0000000..ca69178
--- /dev/null
+++ b/pkg/region/region_test.go
@@ -0,0 +1,93 @@
+// +build unit
+
+package region
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestParse(t *testing.T) {
+	t.Parallel()
+
+	pairs := map[string]*Region{
+		"us":      Regions[US],
+		"Us":      Regions[US],
+		"uS":      Regions[US],
+		"US":      Regions[US],
+		"eu":      Regions[EU],
+		"Eu":      Regions[EU],
+		"eU":      Regions[EU],
+		"EU":      Regions[EU],
+		"staging": Regions[Staging],
+		"Staging": Regions[Staging],
+		"STAGING": Regions[Staging],
+	}
+
+	for k, v := range pairs {
+		result := Parse(k)
+		assert.Equal(t, result, v)
+	}
+
+	// Default is US
+	result := Parse("")
+	assert.Equal(t, result, Regions[US])
+}
+
+func TestString(t *testing.T) {
+	t.Parallel()
+
+	pairs := map[Name]string{
+		US:      "US",
+		EU:      "EU",
+		Staging: "Staging",
+	}
+
+	for k, v := range pairs {
+		result := Regions[k].String()
+		assert.Equal(t, result, v)
+	}
+
+	// Verify that an uninitialized Region (should be 0) isn't known
+	var unk Region
+	result := unk.String()
+	assert.Equal(t, result, "(Unknown)")
+}
+
+func TestInfrastructurURLs(t *testing.T) {
+	t.Parallel()
+
+	pairs := map[Name]string{
+		US:      "https://infra-api.newrelic.com/v2",
+		EU:      "https://infra-api.eu.newrelic.com/v2",
+		Staging: "https://staging-infra-api.newrelic.com/v2",
+	}
+
+	for k, v := range pairs {
+		assert.Equal(t, v, Regions[k].InfrastructureURL())
+	}
+}
+
+func TestSyntheticsURLs(t *testing.T) {
+	t.Parallel()
+
+	pairs := map[Name]string{
+		US:      "https://synthetics.newrelic.com/synthetics/api",
+		EU:      "https://synthetics.eu.newrelic.com/synthetics/api",
+		Staging: "https://staging-synthetics.newrelic.com/synthetics/api",
+	}
+
+	for k, v := range pairs {
+		assert.Equal(t, v, Regions[k].SyntheticsURL())
+	}
+}
+
+func TestConcatURLPaths(t *testing.T) {
+	t.Parallel()
+
+	res, err := concatURLPaths("http://localhost/", []string{"one", "/two", "//three", "four/", "five//"})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "http://localhost/one/two/three/four/five", res)
+}
diff --git a/pkg/synthetics/example_labels_test.go b/pkg/synthetics/example_labels_test.go
index e8286ab..2eea915 100644
--- a/pkg/synthetics/example_labels_test.go
+++ b/pkg/synthetics/example_labels_test.go
@@ -11,9 +11,8 @@ import (
 func Example_labels() {
 	// Initialize the client configuration.  An Admin API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey: os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/synthetics/example_monitor_test.go b/pkg/synthetics/example_monitor_test.go
index a55eeed..5fe9e73 100644
--- a/pkg/synthetics/example_monitor_test.go
+++ b/pkg/synthetics/example_monitor_test.go
@@ -10,9 +10,8 @@ import (
 func Example_monitor() {
 	// Initialize the client configuration.  An Admin API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey: os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/synthetics/example_secure_credentials_test.go b/pkg/synthetics/example_secure_credentials_test.go
index 1a03afd..9c6c18f 100644
--- a/pkg/synthetics/example_secure_credentials_test.go
+++ b/pkg/synthetics/example_secure_credentials_test.go
@@ -10,9 +10,8 @@ import (
 func Example_secureCredentials() {
 	// Initialize the client configuration.  An Admin API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		AdminAPIKey: os.Getenv("NEW_RELIC_ADMIN_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.AdminAPIKey = os.Getenv("NEW_RELIC_ADMIN_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/synthetics/monitor_labels_integration_test.go b/pkg/synthetics/monitor_labels_integration_test.go
index 438f2bf..e4df906 100644
--- a/pkg/synthetics/monitor_labels_integration_test.go
+++ b/pkg/synthetics/monitor_labels_integration_test.go
@@ -4,15 +4,13 @@ package synthetics
 
 import (
 	"fmt"
-	"os"
 	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	nr "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 var (
@@ -32,19 +30,12 @@ var (
 func TestIntegrationGetMonitorLabels(t *testing.T) {
 	t.Parallel()
 
-	apiKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	tc := mock.NewIntegrationTestConfig(t)
 
-	if apiKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_ADMIN_API_KEY to be set")
-	}
-
-	synthetics := New(config.Config{
-		AdminAPIKey: apiKey,
-		LogLevel:    "debug",
-	})
+	synthetics := New(tc)
 
 	// Setup
-	rand := nr.RandSeq(5)
+	rand := mock.RandSeq(5)
 	testIntegrationLabeledMonitor.Name = fmt.Sprintf("test-synthetics-monitor-%s", rand)
 	monitor, err := synthetics.CreateMonitor(testIntegrationLabeledMonitor)
 	require.NoError(t, err)
diff --git a/pkg/synthetics/monitor_labels_test.go b/pkg/synthetics/monitor_labels_test.go
index 80de334..7266c53 100644
--- a/pkg/synthetics/monitor_labels_test.go
+++ b/pkg/synthetics/monitor_labels_test.go
@@ -29,8 +29,11 @@ func TestGetMonitorLabel(t *testing.T) {
 	r, err := synthetics.GetMonitorLabels(testMonitorID)
 	assert.NoError(t, err)
 	assert.Equal(t, 1, len(r))
-	assert.Equal(t, r[0].Type, "Testing")
-	assert.Equal(t, r[0].Value, "Mbnhl")
+	// Don't panic if we failed
+	if len(r) >= 1 {
+		assert.Equal(t, r[0].Type, "Testing")
+		assert.Equal(t, r[0].Value, "Mbnhl")
+	}
 }
 
 func TestAddMonitorLabel(t *testing.T) {
diff --git a/pkg/synthetics/monitor_scripts_integration_test.go b/pkg/synthetics/monitor_scripts_integration_test.go
index d0d271c..aae30ee 100644
--- a/pkg/synthetics/monitor_scripts_integration_test.go
+++ b/pkg/synthetics/monitor_scripts_integration_test.go
@@ -4,13 +4,11 @@ package synthetics
 
 import (
 	"fmt"
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	nr "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 var (
@@ -40,19 +38,11 @@ var (
 func TestIntegrationMonitorScripts(t *testing.T) {
 	t.Parallel()
 
-	apiKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
-
-	if apiKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_ADMIN_API_KEY to be set")
-	}
-
-	synthetics := New(config.Config{
-		AdminAPIKey: apiKey,
-		LogLevel:    "debug",
-	})
+	tc := mock.NewIntegrationTestConfig(t)
+	synthetics := New(tc)
 
 	// Setup
-	rand := nr.RandSeq(5)
+	rand := mock.RandSeq(5)
 	testIntegrationScriptedMonitor.Name = fmt.Sprintf("test-synthetics-monitor-%s", rand)
 	monitor, err := synthetics.CreateMonitor(testIntegrationScriptedMonitor)
 
diff --git a/pkg/synthetics/monitors_integration_test.go b/pkg/synthetics/monitors_integration_test.go
index 8cb4a06..a1c672c 100644
--- a/pkg/synthetics/monitors_integration_test.go
+++ b/pkg/synthetics/monitors_integration_test.go
@@ -4,13 +4,11 @@ package synthetics
 
 import (
 	"fmt"
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	nr "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 var (
@@ -30,23 +28,15 @@ var (
 func TestIntegrationMonitors(t *testing.T) {
 	t.Parallel()
 
-	apiKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
+	tc := mock.NewIntegrationTestConfig(t)
 
-	if apiKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_ADMIN_API_KEY to be set")
-	}
-
-	synthetics := New(config.Config{
-		AdminAPIKey: apiKey,
-		LogLevel:    "debug",
-	})
+	synthetics := New(tc)
 
-	rand := nr.RandSeq(5)
+	rand := mock.RandSeq(5)
 	testIntegrationMonitor.Name = fmt.Sprintf("test-synthetics-monitor-%s", rand)
 
 	// Test: Create
 	created, err := synthetics.CreateMonitor(testIntegrationMonitor)
-	monitorID := created.ID
 
 	require.NoError(t, err)
 	require.NotNil(t, created)
@@ -59,6 +49,7 @@ func TestIntegrationMonitors(t *testing.T) {
 	require.Greater(t, len(monitors), 0)
 
 	// Test: Get
+	monitorID := created.ID
 	monitor, err := synthetics.GetMonitor(monitorID)
 
 	require.NoError(t, err)
diff --git a/pkg/synthetics/secure_credentials_integration_test.go b/pkg/synthetics/secure_credentials_integration_test.go
index abd63c6..6d02d87 100644
--- a/pkg/synthetics/secure_credentials_integration_test.go
+++ b/pkg/synthetics/secure_credentials_integration_test.go
@@ -4,15 +4,13 @@ package synthetics
 
 import (
 	"fmt"
-	"os"
 	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	nr "github.com/newrelic/newrelic-client-go/internal/testing"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 var (
@@ -27,19 +25,11 @@ var (
 func TestIntegrationSecureCredentials(t *testing.T) {
 	t.Parallel()
 
-	apiKey := os.Getenv("NEW_RELIC_ADMIN_API_KEY")
-
-	if apiKey == "" {
-		t.Skipf("acceptance testing requires NEW_RELIC_ADMIN_API_KEY")
-	}
-
-	synthetics := New(config.Config{
-		AdminAPIKey: apiKey,
-		LogLevel:    "debug",
-	})
+	tc := mock.NewIntegrationTestConfig(t)
+	synthetics := New(tc)
 
 	// Setup
-	rand := strings.ToUpper(nr.RandSeq(5))
+	rand := strings.ToUpper(mock.RandSeq(5))
 	key := fmt.Sprintf("TEST_SYNTHETICS_SECURE_CREDENTIAL_%s", rand)
 	testIntegrationSecureCredential.Key = key
 	creds, err := synthetics.GetSecureCredentials()
diff --git a/pkg/synthetics/synthetics_test.go b/pkg/synthetics/synthetics_test.go
index ec82938..81f2ea2 100644
--- a/pkg/synthetics/synthetics_test.go
+++ b/pkg/synthetics/synthetics_test.go
@@ -10,32 +10,9 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	"github.com/newrelic/newrelic-client-go/internal/region"
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
-func TestBaseURLs(t *testing.T) {
-	t.Parallel()
-
-	pairs := map[region.Region]string{
-		region.US:      "https://synthetics.newrelic.com/synthetics/api",
-		region.EU:      "https://synthetics.eu.newrelic.com/synthetics/api",
-		region.Staging: "https://staging-synthetics.newrelic.com/synthetics/api",
-	}
-
-	// Default should be region.US
-	a := New(config.Config{})
-	assert.Equal(t, pairs[region.US], a.client.GetBaseURL())
-
-	for k, v := range pairs {
-		b := New(config.Config{
-			Region: config.RegionType(k.String()),
-		})
-
-		assert.Equal(t, v, b.client.GetBaseURL())
-	}
-}
-
 // TestError checks that messages are reported in the correct
 // order by going through priorities backwards
 func TestError(t *testing.T) {
@@ -62,27 +39,15 @@ func TestError(t *testing.T) {
 
 }
 
-// nolint
-func newTestClient(handler http.Handler) Synthetics {
+func newTestClient(t *testing.T, handler http.Handler) Synthetics {
 	ts := httptest.NewServer(handler)
+	tc := mock.NewTestConfig(t, ts)
 
-	c := New(config.Config{
-		AdminAPIKey:       "abc123",
-		SyntheticsBaseURL: ts.URL,
-		UserAgent:         "newrelic/newrelic-client-go",
-		LogLevel:          "debug",
-	})
-
-	return c
+	return New(tc)
 }
 
-// nolint
-func newMockResponse(
-	t *testing.T,
-	mockJSONResponse string,
-	statusCode int,
-) Synthetics {
-	return newTestClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+func newMockResponse(t *testing.T, mockJSONResponse string, statusCode int) Synthetics {
+	return newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(statusCode)
 
diff --git a/pkg/workloads/example_basic_test.go b/pkg/workloads/example_basic_test.go
index d0e3618..aa02404 100644
--- a/pkg/workloads/example_basic_test.go
+++ b/pkg/workloads/example_basic_test.go
@@ -13,9 +13,8 @@ import (
 func Example_basic() {
 	// Initialize the client configuration.  A Personal API key is required to
 	// communicate with the backend API.
-	cfg := config.Config{
-		PersonalAPIKey: os.Getenv("NEW_RELIC_API_KEY"),
-	}
+	cfg := config.New()
+	cfg.PersonalAPIKey = os.Getenv("NEW_RELIC_API_KEY")
 
 	// Initialize the client.
 	client := New(cfg)
diff --git a/pkg/workloads/workload_integration_test.go b/pkg/workloads/workload_integration_test.go
index d179dfc..13213ef 100644
--- a/pkg/workloads/workload_integration_test.go
+++ b/pkg/workloads/workload_integration_test.go
@@ -3,12 +3,11 @@
 package workloads
 
 import (
-	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
-	"github.com/newrelic/newrelic-client-go/pkg/config"
+	mock "github.com/newrelic/newrelic-client-go/internal/testing"
 )
 
 var (
@@ -99,17 +98,8 @@ func TestIntegrationWorkload(t *testing.T) {
 	require.NotNil(t, deleted)
 }
 
-// nolint
 func newIntegrationTestClient(t *testing.T) Workloads {
-	apiKey := os.Getenv("NEW_RELIC_API_KEY")
+	tc := mock.NewIntegrationTestConfig(t)
 
-	if apiKey == "" {
-		t.Skipf("acceptance testing for graphql requires your personal API key")
-	}
-
-	return New(config.Config{
-		PersonalAPIKey: apiKey,
-		UserAgent:      "newrelic/newrelic-client-go",
-		LogLevel:       "debug",
-	})
+	return New(tc)
 }