Repository: mailgun/mailgun-go
Pull request #377 (2025-01-02 18:22:54)

DE-1383 Move the API version out of the base URL


Patch:
diff --git a/README.md b/README.md
index beb7485..aa7cbcd 100644
--- a/README.md
+++ b/README.md
@@ -38,8 +38,8 @@ func main() {
 	// Create an instance of the Mailgun Client
 	mg := mailgun.NewMailgun(privateAPIKey)
 	
-	//When you have an EU-domain, you must specify the endpoint:
-	//mg.SetAPIBase("https://api.eu.mailgun.net/v3")
+	// When you have an EU domain, you must specify the endpoint:
+	// err := mg.SetAPIBase(mailgun.APIBaseEU)
 
 	sender := "sender@example.com"
 	subject := "Fancy subject!"
diff --git a/analytics.go b/analytics.go
index 7a421cf..25d5271 100644
--- a/analytics.go
+++ b/analytics.go
@@ -2,7 +2,6 @@ package mailgun
 
 import (
 	"context"
-	"strings"
 
 	"github.com/mailgun/errors"
 )
@@ -35,15 +34,11 @@ type MetricsPagination struct {
 //
 // https://documentation.mailgun.com/docs/mailgun/api-reference/openapi-final/tag/Metrics/
 func (mg *MailgunImpl) ListMetrics(opts MetricsOptions) (*MetricsIterator, error) {
-	if !strings.HasSuffix(mg.APIBase(), "/v1") {
-		return nil, errors.New("only v1 API is supported")
-	}
-
 	if opts.Pagination.Limit == 0 {
 		opts.Pagination.Limit = 10
 	}
 
-	req := newHTTPRequest(generateApiUrl(mg, metricsEndpoint))
+	req := newHTTPRequest(generateApiUrl(mg, 1, metricsEndpoint))
 	req.setClient(mg.HTTPClient())
 	req.setBasicAuth(basicAuthUser, mg.APIKey())
 
diff --git a/bounces.go b/bounces.go
index 405d861..cba6713 100644
--- a/bounces.go
+++ b/bounces.go
@@ -35,7 +35,7 @@ type bouncesListResponse struct {
 // and the slice of bounces specified, if successful.
 // Note that the length of the slice may be smaller than the total number of bounces.
 func (mg *MailgunImpl) ListBounces(domain string, opts *ListOptions) *BouncesIterator {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	if opts != nil {
@@ -147,7 +147,7 @@ func (ci *BouncesIterator) fetch(ctx context.Context, url string) error {
 
 // GetBounce retrieves a single bounce record, if any exist, for the given recipient address.
 func (mg *MailgunImpl) GetBounce(ctx context.Context, domain, address string) (Bounce, error) {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -173,7 +173,7 @@ func (mg *MailgunImpl) GetBounce(ctx context.Context, domain, address string) (B
 // Note that both code and error exist as strings, even though
 // code will report as a number.
 func (mg *MailgunImpl) AddBounce(ctx context.Context, domain, address, code, bounceError string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -191,7 +191,7 @@ func (mg *MailgunImpl) AddBounce(ctx context.Context, domain, address, code, bou
 
 // Add Bounces adds a list of bounces to the bounce list
 func (mg *MailgunImpl) AddBounces(ctx context.Context, domain string, bounces []Bounce) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -203,7 +203,7 @@ func (mg *MailgunImpl) AddBounces(ctx context.Context, domain string, bounces []
 
 // DeleteBounce removes all bounces associted with the provided e-mail address.
 func (mg *MailgunImpl) DeleteBounce(ctx context.Context, domain, address string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain) + "/" + address)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -212,7 +212,7 @@ func (mg *MailgunImpl) DeleteBounce(ctx context.Context, domain, address string)
 
 // DeleteBounceList removes all bounces in the bounce list
 func (mg *MailgunImpl) DeleteBounceList(ctx context.Context, domain string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, bouncesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, bouncesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
diff --git a/domains.go b/domains.go
index cb01562..15acac5 100644
--- a/domains.go
+++ b/domains.go
@@ -92,7 +92,7 @@ func (mg *MailgunImpl) ListDomains(opts *ListOptions) *DomainsIterator {
 	}
 	return &DomainsIterator{
 		mg:                  mg,
-		url:                 generateApiUrl(mg, domainsEndpoint),
+		url:                 generateApiUrl(mg, 3, domainsEndpoint),
 		domainsListResponse: domainsListResponse{TotalCount: -1},
 		limit:               limit,
 	}
@@ -233,7 +233,7 @@ func (ri *DomainsIterator) fetch(ctx context.Context, skip, limit int) error {
 
 // GetDomain retrieves detailed information about the named domain.
 func (mg *MailgunImpl) GetDomain(ctx context.Context, domain string) (DomainResponse, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain)
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var resp DomainResponse
@@ -242,7 +242,7 @@ func (mg *MailgunImpl) GetDomain(ctx context.Context, domain string) (DomainResp
 }
 
 func (mg *MailgunImpl) VerifyDomain(ctx context.Context, domain string) (string, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/verify")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/verify")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -254,7 +254,7 @@ func (mg *MailgunImpl) VerifyDomain(ctx context.Context, domain string) (string,
 
 // VerifyAndReturnDomain verifies & retrieves detailed information about the named domain.
 func (mg *MailgunImpl) VerifyAndReturnDomain(ctx context.Context, domain string) (DomainResponse, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/verify")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/verify")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -282,7 +282,7 @@ type CreateDomainOptions struct {
 // The wildcard parameter instructs Mailgun to treat all subdomains of this domain uniformly if true,
 // and as different domains if false.
 func (mg *MailgunImpl) CreateDomain(ctx context.Context, name string, opts *CreateDomainOptions) (DomainResponse, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint))
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -319,7 +319,7 @@ func (mg *MailgunImpl) CreateDomain(ctx context.Context, name string, opts *Crea
 
 // GetDomainConnection returns delivery connection settings for the defined domain
 func (mg *MailgunImpl) GetDomainConnection(ctx context.Context, domain string) (DomainConnection, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/connection")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/connection")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var resp domainConnectionResponse
@@ -327,9 +327,9 @@ func (mg *MailgunImpl) GetDomainConnection(ctx context.Context, domain string) (
 	return resp.Connection, err
 }
 
-// Updates the specified delivery connection settings for the defined domain
+// UpdateDomainConnection updates the specified delivery connection settings for the defined domain
 func (mg *MailgunImpl) UpdateDomainConnection(ctx context.Context, domain string, settings DomainConnection) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/connection")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/connection")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -342,7 +342,7 @@ func (mg *MailgunImpl) UpdateDomainConnection(ctx context.Context, domain string
 
 // DeleteDomain instructs Mailgun to dispose of the named domain name
 func (mg *MailgunImpl) DeleteDomain(ctx context.Context, name string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + name)
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -351,7 +351,7 @@ func (mg *MailgunImpl) DeleteDomain(ctx context.Context, name string) error {
 
 // GetDomainTracking returns tracking settings for a domain
 func (mg *MailgunImpl) GetDomainTracking(ctx context.Context, domain string) (DomainTracking, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var resp domainTrackingResponse
@@ -360,7 +360,7 @@ func (mg *MailgunImpl) GetDomainTracking(ctx context.Context, domain string) (Do
 }
 
 func (mg *MailgunImpl) UpdateClickTracking(ctx context.Context, domain, active string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/click")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking/click")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -371,7 +371,7 @@ func (mg *MailgunImpl) UpdateClickTracking(ctx context.Context, domain, active s
 }
 
 func (mg *MailgunImpl) UpdateUnsubscribeTracking(ctx context.Context, domain, active, htmlFooter, textFooter string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/unsubscribe")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking/unsubscribe")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -384,7 +384,7 @@ func (mg *MailgunImpl) UpdateUnsubscribeTracking(ctx context.Context, domain, ac
 }
 
 func (mg *MailgunImpl) UpdateOpenTracking(ctx context.Context, domain, active string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/open")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/tracking/open")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -396,7 +396,7 @@ func (mg *MailgunImpl) UpdateOpenTracking(ctx context.Context, domain, active st
 
 // Update the DKIM selector for a domain
 func (mg *MailgunImpl) UpdateDomainDkimSelector(ctx context.Context, domain, dkimSelector string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/dkim_selector")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/dkim_selector")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -408,7 +408,7 @@ func (mg *MailgunImpl) UpdateDomainDkimSelector(ctx context.Context, domain, dki
 
 // Update the CNAME used for tracking opens and clicks
 func (mg *MailgunImpl) UpdateDomainTrackingWebPrefix(ctx context.Context, domain, webPrefix string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/web_prefix")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/web_prefix")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -426,7 +426,7 @@ type UpdateDomainOptions struct {
 // UpdateDomain updates a domain's attributes.
 // Currently only the web_scheme update is supported, spam_action and wildcard are to be added.
 func (mg *MailgunImpl) UpdateDomain(ctx context.Context, name string, opts *UpdateDomainOptions) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + name)
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
diff --git a/email_validation.go b/email_validation.go
index d9b484a..123e3ce 100644
--- a/email_validation.go
+++ b/email_validation.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"net/http"
 	"os"
-	"strings"
 
 	"github.com/mailgun/errors"
 )
@@ -22,6 +21,7 @@ type EmailVerificationParts struct {
 
 // EmailVerification records basic facts about a validated e-mail address.
 // See the ValidateEmail method and example for more details.
+// TODO(v5): remove /v3 validations fields(Reason)
 type EmailVerification struct {
 	// Indicates whether an email address conforms to IETF RFC standards.
 	IsValid bool `json:"is_valid"`
@@ -148,16 +148,11 @@ func (m *EmailValidatorImpl) APIKey() string {
 // It may also be used to break an email address into its sub-components. If user has set the
 // TODO(v5): move to *MailgunImpl?
 func (m *EmailValidatorImpl) ValidateEmail(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) {
-	// TODO(DE-1383): remove check:
-	if strings.HasSuffix(m.APIBase(), "/v4") {
-		return m.validateV4(ctx, email, mailBoxVerify)
-	}
-
-	return EmailVerification{}, errors.New("ValidateEmail: only v4 is supported")
+	return m.validateV4(ctx, email, mailBoxVerify)
 }
 
 func (m *EmailValidatorImpl) validateV4(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) {
-	r := newHTTPRequest(fmt.Sprintf("%s/address/validate", m.APIBase()))
+	r := newHTTPRequest(fmt.Sprintf("%s/v4/address/validate", m.APIBase()))
 	r.setClient(m.Client())
 	r.addParameter("address", email)
 	if mailBoxVerify {
diff --git a/events.go b/events.go
index d17e63a..ee311d8 100644
--- a/events.go
+++ b/events.go
@@ -38,7 +38,7 @@ type EventIterator struct {
 
 // ListEvents creates a new iterator to fetch a page of events from the events api
 func (mg *MailgunImpl) ListEvents(domain string, opts *ListEventOptions) *EventIterator {
-	url := generateApiUrlWithDomain(mg, eventsEndpoint, domain)
+	url := generateApiV3UrlWithDomain(mg, eventsEndpoint, domain)
 	return mg.listEvents(url, opts)
 }
 
diff --git a/exports.go b/exports.go
index dc0a4db..c222374 100644
--- a/exports.go
+++ b/exports.go
@@ -19,7 +19,7 @@ type Export struct {
 
 // Create an export based on the URL given
 func (mg *MailgunImpl) CreateExport(ctx context.Context, url string) error {
-	r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint))
+	r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -31,7 +31,7 @@ func (mg *MailgunImpl) CreateExport(ctx context.Context, url string) error {
 
 // List all exports created within the past 24 hours
 func (mg *MailgunImpl) ListExports(ctx context.Context, url string) ([]Export, error) {
-	r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint))
+	r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint))
 	r.setClient(mg.HTTPClient())
 	if url != "" {
 		r.addParameter("url", url)
@@ -52,7 +52,7 @@ func (mg *MailgunImpl) ListExports(ctx context.Context, url string) ([]Export, e
 
 // GetExport gets an export by id
 func (mg *MailgunImpl) GetExport(ctx context.Context, id string) (Export, error) {
-	r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint) + "/" + id)
+	r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint) + "/" + id)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var resp Export
@@ -63,7 +63,7 @@ func (mg *MailgunImpl) GetExport(ctx context.Context, id string) (Export, error)
 // Download an export by ID. This will respond with a '302 Moved'
 // with the Location header of temporary S3 URL if it is available.
 func (mg *MailgunImpl) GetExportLink(ctx context.Context, id string) (string, error) {
-	r := newHTTPRequest(generateApiUrl(mg, exportsEndpoint) + "/" + id + "/download_url")
+	r := newHTTPRequest(generateApiUrl(mg, 3, exportsEndpoint) + "/" + id + "/download_url")
 	c := mg.HTTPClient()
 
 	// Ensure the client doesn't attempt to retry
diff --git a/httphelpers.go b/httphelpers.go
index f2212bd..c6cf049 100644
--- a/httphelpers.go
+++ b/httphelpers.go
@@ -17,7 +17,7 @@ import (
 	"github.com/mailgun/errors"
 )
 
-var validURL = regexp.MustCompile(`/v[1-5].*`)
+var invalidURL = regexp.MustCompile(`/v\d+.*`)
 
 type httpRequest struct {
 	URL               string
@@ -370,10 +370,6 @@ func (r *httpRequest) generateUrlWithParameters() (string, error) {
 		return "", err
 	}
 
-	if !validURL.MatchString(uri.Path) {
-		return "", errors.New(`APIBase must end with a /v1, /v2, /v3 or /v4; SetAPIBase("https://host/v3")`)
-	}
-
 	q := uri.Query()
 	if len(r.Parameters) > 0 {
 		for name, values := range r.Parameters {
diff --git a/ips.go b/ips.go
index 6cb37fb..7a94457 100644
--- a/ips.go
+++ b/ips.go
@@ -20,7 +20,7 @@ type okResp struct {
 
 // ListIPS returns a list of IPs assigned to your account
 func (mg *MailgunImpl) ListIPS(ctx context.Context, dedicated bool) ([]IPAddress, error) {
-	r := newHTTPRequest(generateApiUrl(mg, ipsEndpoint))
+	r := newHTTPRequest(generateApiUrl(mg, 3, ipsEndpoint))
 	r.setClient(mg.HTTPClient())
 	if dedicated {
 		r.addParameter("dedicated", "true")
@@ -40,7 +40,7 @@ func (mg *MailgunImpl) ListIPS(ctx context.Context, dedicated bool) ([]IPAddress
 
 // GetIP returns information about the specified IP
 func (mg *MailgunImpl) GetIP(ctx context.Context, ip string) (IPAddress, error) {
-	r := newHTTPRequest(generateApiUrl(mg, ipsEndpoint) + "/" + ip)
+	r := newHTTPRequest(generateApiUrl(mg, 3, ipsEndpoint) + "/" + ip)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var resp IPAddress
@@ -50,7 +50,7 @@ func (mg *MailgunImpl) GetIP(ctx context.Context, ip string) (IPAddress, error)
 
 // ListDomainIPS returns a list of IPs currently assigned to the specified domain.
 func (mg *MailgunImpl) ListDomainIPS(ctx context.Context, domain string) ([]IPAddress, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/ips")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/ips")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -67,7 +67,7 @@ func (mg *MailgunImpl) ListDomainIPS(ctx context.Context, domain string) ([]IPAd
 
 // Assign a dedicated IP to the domain specified.
 func (mg *MailgunImpl) AddDomainIP(ctx context.Context, domain, ip string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/ips")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/ips")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -79,7 +79,7 @@ func (mg *MailgunImpl) AddDomainIP(ctx context.Context, domain, ip string) error
 
 // Unassign an IP from the domain specified.
 func (mg *MailgunImpl) DeleteDomainIP(ctx context.Context, domain, ip string) error {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/ips/" + ip)
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/ips/" + ip)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
diff --git a/limits.go b/limits.go
index 4bff2e2..2e73ead 100644
--- a/limits.go
+++ b/limits.go
@@ -9,7 +9,7 @@ type TagLimits struct {
 
 // GetTagLimits returns tracking settings for a domain
 func (mg *MailgunImpl) GetTagLimits(ctx context.Context, domain string) (TagLimits, error) {
-	r := newHTTPRequest(generateApiUrl(mg, domainsEndpoint) + "/" + domain + "/limits/tag")
+	r := newHTTPRequest(generateApiUrl(mg, 3, domainsEndpoint) + "/" + domain + "/limits/tag")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var resp TagLimits
diff --git a/mailgun.go b/mailgun.go
index 6e8ddfd..cfe7950 100644
--- a/mailgun.go
+++ b/mailgun.go
@@ -88,9 +88,10 @@ var Debug = false
 
 const (
 	// APIBase - base URL the library uses to contact mailgun. Use SetAPIBase() to override
-	APIBase              = "https://api.mailgun.net/v3"
-	APIBaseUS            = APIBase
-	APIBaseEU            = "https://api.eu.mailgun.net/v3"
+	APIBase   = "https://api.mailgun.net"
+	APIBaseUS = APIBase
+	APIBaseEU = "https://api.eu.mailgun.net"
+
 	messagesEndpoint     = "messages"
 	mimeMessagesEndpoint = "messages.mime"
 	bouncesEndpoint      = "bounces"
@@ -108,7 +109,8 @@ const (
 	templatesEndpoint    = "templates"
 	accountsEndpoint     = "accounts"
 	subaccountsEndpoint  = "subaccounts"
-	OnBehalfOfHeader     = "X-Mailgun-On-Behalf-Of"
+
+	OnBehalfOfHeader = "X-Mailgun-On-Behalf-Of"
 )
 
 // Mailgun defines the supported subset of the Mailgun API.
@@ -124,7 +126,7 @@ type Mailgun interface {
 	APIKey() string
 	HTTPClient() *http.Client
 	SetHTTPClient(client *http.Client)
-	SetAPIBase(url string)
+	SetAPIBase(url string) error
 	AddOverrideHeader(k string, v string)
 
 	// Send attempts to queue a message (see CommonMessage, NewMessage, and its methods) for delivery.
@@ -274,7 +276,10 @@ func NewMailgunFromEnv() (*MailgunImpl, error) {
 
 	url := os.Getenv("MG_URL")
 	if url != "" {
-		mg.SetAPIBase(url)
+		err := mg.SetAPIBase(url)
+		if err != nil {
+			return nil, err
+		}
 	}
 
 	webhookSigningKey := os.Getenv("MG_WEBHOOK_SIGNING_KEY")
@@ -339,9 +344,14 @@ func (mg *MailgunImpl) RemoveOnBehalfOfSubaccount() {
 //	mg.SetAPIBase(mailgun.APIBaseUS)
 //
 //	// Set a custom base API
-//	mg.SetAPIBase("https://localhost/v3")
-func (mg *MailgunImpl) SetAPIBase(address string) {
+//	mg.SetAPIBase("https://localhost")
+func (mg *MailgunImpl) SetAPIBase(address string) error {
+	if invalidURL.MatchString(address) {
+		return errors.New(`APIBase must not contain a version; SetAPIBase("https://host")`)
+	}
+
 	mg.apiBase = address
+	return nil
 }
 
 // AddOverrideHeader allows the user to specify additional headers that will be included in the HTTP request
@@ -358,48 +368,54 @@ type ListOptions struct {
 	Limit int
 }
 
-// generateApiUrlWithDomain renders a URL for an API endpoint using the domain and endpoint name.
-func generateApiUrlWithDomain(m Mailgun, endpoint, domain string) string {
-	return fmt.Sprintf("%s/%s/%s", m.APIBase(), domain, endpoint)
+// TODO(vtopc): sort all these generate URL functions(some are generateApi...Url, other are generate...ApiUrl)
+
+func generateApiUrlWithDomain(m Mailgun, version int, endpoint, domain string) string {
+	return fmt.Sprintf("%s/v%d/%s/%s", m.APIBase(), version, domain, endpoint)
+}
+
+// generateApiV3UrlWithDomain renders a URL for an API endpoint using the domain and endpoint name.
+func generateApiV3UrlWithDomain(m Mailgun, endpoint, domain string) string {
+	return generateApiUrlWithDomain(m, 3, endpoint, domain)
 }
 
 // generateMemberApiUrl renders a URL relevant for specifying mailing list members.
 // The address parameter refers to the mailing list in question.
 func generateMemberApiUrl(m Mailgun, endpoint, address string) string {
-	return fmt.Sprintf("%s/%s/%s/members", m.APIBase(), endpoint, address)
+	return fmt.Sprintf("%s/v3/%s/%s/members", m.APIBase(), endpoint, address)
 }
 
-// generateApiUrlWithTarget works as generateApiUrl
+// generateApiV3UrlWithTarget works as generateApiV3UrlWithDomain
 // but consumes an additional resource parameter called 'target'.
-func generateApiUrlWithTarget(m Mailgun, endpoint, domain, target string) string {
+func generateApiV3UrlWithTarget(m Mailgun, endpoint, domain, target string) string {
 	tail := ""
 	if target != "" {
 		tail = fmt.Sprintf("/%s", target)
 	}
-	return fmt.Sprintf("%s%s", generateApiUrlWithDomain(m, endpoint, domain), tail)
+	return fmt.Sprintf("%s%s", generateApiV3UrlWithDomain(m, endpoint, domain), tail)
 }
 
-// generateDomainsApiUrl renders a URL as generateApiUrlWithDomain, but
+// generateV3DomainsApiUrl renders a URL as generateApiV3UrlWithDomain, but
 // addresses a family of functions which have a non-standard URL structure.
 // Most URLs consume a domain in the 2nd position, but some endpoints
 // require the word "domains" to be there instead.
-func generateDomainsApiUrl(m Mailgun, endpoint, domain string) string {
-	return fmt.Sprintf("%s/domains/%s/%s", m.APIBase(), domain, endpoint)
+func generateV3DomainsApiUrl(m Mailgun, endpoint, domain string) string {
+	return fmt.Sprintf("%s/v3/domains/%s/%s", m.APIBase(), domain, endpoint)
 }
 
-// generateCredentialsUrl renders a URL as generateDomainsApiUrl,
+// generateCredentialsUrl renders a URL as generateV3DomainsApiUrl,
 // but focuses on the SMTP credentials family of API functions.
 func generateCredentialsUrl(m Mailgun, domain, login string) string {
 	tail := ""
 	if login != "" {
 		tail = fmt.Sprintf("/%s", login)
 	}
-	return generateDomainsApiUrl(m, fmt.Sprintf("credentials%s", tail), domain)
+	return generateV3DomainsApiUrl(m, fmt.Sprintf("credentials%s", tail), domain)
 }
 
 // generateApiUrl returns domain agnostic URL.
-func generateApiUrl(m Mailgun, endpoint string) string {
-	return fmt.Sprintf("%s/%s", m.APIBase(), endpoint)
+func generateApiUrl(m Mailgun, version int, endpoint string) string {
+	return fmt.Sprintf("%s/v%d/%s", m.APIBase(), version, endpoint)
 }
 
 // formatMailgunTime translates a timestamp into a human-readable form.
diff --git a/mailing_lists.go b/mailing_lists.go
index ccaa0c3..a1f3613 100644
--- a/mailing_lists.go
+++ b/mailing_lists.go
@@ -63,7 +63,7 @@ type ListsIterator struct {
 
 // ListMailingLists returns the specified set of mailing lists administered by your account.
 func (mg *MailgunImpl) ListMailingLists(opts *ListOptions) *ListsIterator {
-	r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/pages")
+	r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/pages")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	if opts != nil {
@@ -174,7 +174,7 @@ func (li *ListsIterator) fetch(ctx context.Context, url string) error {
 // while AccessLevel defaults to Everyone
 // and ReplyPreference defaults to List.
 func (mg *MailgunImpl) CreateMailingList(ctx context.Context, prototype MailingList) (MailingList, error) {
-	r := newHTTPRequest(generateApiUrl(mg, listsEndpoint))
+	r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -205,7 +205,7 @@ func (mg *MailgunImpl) CreateMailingList(ctx context.Context, prototype MailingL
 // DeleteMailingList removes all current members of the list, then removes the list itself.
 // Attempts to send e-mail to the list will fail subsequent to this call.
 func (mg *MailgunImpl) DeleteMailingList(ctx context.Context, addr string) error {
-	r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/" + addr)
+	r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/" + addr)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -215,7 +215,7 @@ func (mg *MailgunImpl) DeleteMailingList(ctx context.Context, addr string) error
 // GetMailingList allows your application to recover the complete List structure
 // representing a mailing list, so long as you have its e-mail address.
 func (mg *MailgunImpl) GetMailingList(ctx context.Context, addr string) (MailingList, error) {
-	r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/" + addr)
+	r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/" + addr)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	response, err := makeGetRequest(ctx, r)
@@ -236,7 +236,7 @@ func (mg *MailgunImpl) GetMailingList(ctx context.Context, addr string) (Mailing
 // e-mail sent to the old address will not succeed.
 // Make sure you account for the change accordingly.
 func (mg *MailgunImpl) UpdateMailingList(ctx context.Context, addr string, prototype MailingList) (MailingList, error) {
-	r := newHTTPRequest(generateApiUrl(mg, listsEndpoint) + "/" + addr)
+	r := newHTTPRequest(generateApiUrl(mg, 3, listsEndpoint) + "/" + addr)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
diff --git a/messages.go b/messages.go
index 0acc65c..a6ace90 100644
--- a/messages.go
+++ b/messages.go
@@ -684,7 +684,7 @@ func (mg *MailgunImpl) Send(ctx context.Context, m SendableMessage) (mes, id str
 		return "", "", err
 	}
 
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, m.Endpoint(), m.Domain()))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, m.Endpoint(), m.Domain()))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	// Override any HTTP headers if provided
diff --git a/messages_v5.go b/messages_v5.go
index 1204f44..4a7c313 100644
--- a/messages_v5.go
+++ b/messages_v5.go
@@ -440,7 +440,7 @@ func (mg *MailgunImpl) sendV5(ctx context.Context, m SendableMessage) (mes, id s
 		return "", "", err
 	}
 
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, m.Endpoint(), m.Domain()))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, m.Endpoint(), m.Domain()))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	// Override any HTTP headers if provided
diff --git a/mock.go b/mock.go
index 4d65e9a..343876e 100644
--- a/mock.go
+++ b/mock.go
@@ -17,9 +17,7 @@ import (
 
 type MockServer interface {
 	Stop()
-	URL1() string
-	URL4() string
-	URL3() string
+	URL() string
 	DomainIPS() []string
 	DomainList() []DomainContainer
 	ExportList() []Export
@@ -151,17 +149,8 @@ func (ms *mockServer) Stop() {
 	ms.srv.Close()
 }
 
-func (ms *mockServer) URL1() string {
-	return ms.srv.URL + "/v1"
-}
-
-// URL3 returns the URL used to connect to the mock server
-func (ms *mockServer) URL3() string {
-	return ms.srv.URL + "/v3"
-}
-
-func (ms *mockServer) URL4() string {
-	return ms.srv.URL + "/v4"
+func (ms *mockServer) URL() string {
+	return ms.srv.URL
 }
 
 func toJSON(w http.ResponseWriter, obj any) {
diff --git a/mock_messages.go b/mock_messages.go
index afb0e1d..539a73a 100644
--- a/mock_messages.go
+++ b/mock_messages.go
@@ -34,7 +34,7 @@ func (ms *mockServer) createMessages(w http.ResponseWriter, r *http.Request) {
 		stored.Name = events.EventStored
 		stored.Timestamp = TimeToFloat(time.Now().UTC())
 		stored.ID = id
-		stored.Storage.URL = ms.URL3() + "/se.storage.url/messages/" + id
+		stored.Storage.URL = ms.URL() + "/v3/se.storage.url/messages/" + id
 		stored.Storage.Key = id
 		stored.Message.Headers = events.MessageHeaders{
 			Subject:   r.FormValue("subject"),
diff --git a/routes.go b/routes.go
index bbf2edd..4693f6e 100644
--- a/routes.go
+++ b/routes.go
@@ -118,7 +118,7 @@ func (mg *MailgunImpl) ListRoutes(opts *ListOptions) *RoutesIterator {
 
 	return &RoutesIterator{
 		mg:                 mg,
-		url:                generateApiUrl(mg, routesEndpoint),
+		url:                generateApiUrl(mg, 3, routesEndpoint),
 		routesListResponse: routesListResponse{TotalCount: -1},
 		limit:              limit,
 	}
@@ -262,7 +262,7 @@ func (ri *RoutesIterator) fetch(ctx context.Context, skip, limit int) error {
 // only a subset of the fields influence the operation.
 // See the Route structure definition for more details.
 func (mg *MailgunImpl) CreateRoute(ctx context.Context, prototype Route) (_ignored Route, err error) {
-	r := newHTTPRequest(generateApiUrl(mg, routesEndpoint))
+	r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -284,7 +284,7 @@ func (mg *MailgunImpl) CreateRoute(ctx context.Context, prototype Route) (_ignor
 // To avoid ambiguity, Mailgun identifies the route by unique ID.
 // See the Route structure definition and the Mailgun API documentation for more details.
 func (mg *MailgunImpl) DeleteRoute(ctx context.Context, id string) error {
-	r := newHTTPRequest(generateApiUrl(mg, routesEndpoint) + "/" + id)
+	r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint) + "/" + id)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -293,7 +293,7 @@ func (mg *MailgunImpl) DeleteRoute(ctx context.Context, id string) error {
 
 // GetRoute retrieves the complete route definition associated with the unique route ID.
 func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) {
-	r := newHTTPRequest(generateApiUrl(mg, routesEndpoint) + "/" + id)
+	r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint) + "/" + id)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var envelope struct {
@@ -312,7 +312,7 @@ func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) {
 // Only those route fields which are non-zero or non-empty are updated.
 // All other fields remain as-is.
 func (mg *MailgunImpl) UpdateRoute(ctx context.Context, id string, route Route) (Route, error) {
-	r := newHTTPRequest(generateApiUrl(mg, routesEndpoint) + "/" + id)
+	r := newHTTPRequest(generateApiUrl(mg, 3, routesEndpoint) + "/" + id)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
diff --git a/spam_complaints.go b/spam_complaints.go
index 4494ace..dcaf50b 100644
--- a/spam_complaints.go
+++ b/spam_complaints.go
@@ -26,7 +26,7 @@ type complaintsResponse struct {
 // Recipients of your messages can click on a link which sends feedback to Mailgun
 // indicating that the message they received is, to them, spam.
 func (mg *MailgunImpl) ListComplaints(domain string, opts *ListOptions) *ComplaintsIterator {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	if opts != nil {
@@ -139,7 +139,7 @@ func (ci *ComplaintsIterator) fetch(ctx context.Context, url string) error {
 // GetComplaint returns a single complaint record filed by a recipient at the email address provided.
 // If no complaint exists, the Complaint instance returned will be empty.
 func (mg *MailgunImpl) GetComplaint(ctx context.Context, domain, address string) (Complaint, error) {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -151,7 +151,7 @@ func (mg *MailgunImpl) GetComplaint(ctx context.Context, domain, address string)
 // CreateComplaint registers the specified address as a recipient who has complained of receiving spam
 // from your domain.
 func (mg *MailgunImpl) CreateComplaint(ctx context.Context, domain, address string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -161,7 +161,7 @@ func (mg *MailgunImpl) CreateComplaint(ctx context.Context, domain, address stri
 }
 
 func (mg *MailgunImpl) CreateComplaints(ctx context.Context, domain string, addresses []string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -179,7 +179,7 @@ func (mg *MailgunImpl) CreateComplaints(ctx context.Context, domain string, addr
 // DeleteComplaint removes a previously registered e-mail address from the list of people who complained
 // of receiving spam from your domain.
 func (mg *MailgunImpl) DeleteComplaint(ctx context.Context, domain, address string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, complaintsEndpoint, domain) + "/" + address)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
diff --git a/subaccounts.go b/subaccounts.go
index 199f05b..316b4cf 100644
--- a/subaccounts.go
+++ b/subaccounts.go
@@ -245,5 +245,5 @@ func (mg *MailgunImpl) DisableSubaccount(ctx context.Context, subaccountId strin
 }
 
 func generateSubaccountsApiUrl(m Mailgun) string {
-	return fmt.Sprintf("%s/%s/%s", m.APIBase(), accountsEndpoint, subaccountsEndpoint)
+	return fmt.Sprintf("%s/v3/%s/%s", m.APIBase(), accountsEndpoint, subaccountsEndpoint)
 }
diff --git a/tags.go b/tags.go
index 72b6c83..f21e922 100644
--- a/tags.go
+++ b/tags.go
@@ -28,7 +28,7 @@ type ListTagOptions struct {
 
 // DeleteTag removes all counters for a particular tag, including the tag itself.
 func (mg *MailgunImpl) DeleteTag(ctx context.Context, domain, tag string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -37,7 +37,7 @@ func (mg *MailgunImpl) DeleteTag(ctx context.Context, domain, tag string) error
 
 // GetTag retrieves metadata about the tag from the api
 func (mg *MailgunImpl) GetTag(ctx context.Context, domain, tag string) (Tag, error) {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, tagsEndpoint, domain) + "/" + tag)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var tagItem Tag
@@ -58,7 +58,7 @@ func (mg *MailgunImpl) GetTag(ctx context.Context, domain, tag string) (Tag, err
 //		log.Fatal(it.Err())
 //	}
 func (mg *MailgunImpl) ListTags(domain string, opts *ListTagOptions) *TagIterator {
-	req := newHTTPRequest(generateApiUrlWithDomain(mg, tagsEndpoint, domain))
+	req := newHTTPRequest(generateApiV3UrlWithDomain(mg, tagsEndpoint, domain))
 	if opts != nil {
 		if opts.Limit != 0 {
 			req.addParameter("limit", strconv.Itoa(opts.Limit))
diff --git a/template.go b/template.go
index ce96098..8951bea 100644
--- a/template.go
+++ b/template.go
@@ -33,7 +33,7 @@ type templateListResp struct {
 
 // Create a new template which can be used to attach template versions to
 func (mg *MailgunImpl) CreateTemplate(ctx context.Context, domain string, template *Template) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -69,7 +69,7 @@ func (mg *MailgunImpl) CreateTemplate(ctx context.Context, domain string, templa
 
 // GetTemplate gets a template given the template name
 func (mg *MailgunImpl) GetTemplate(ctx context.Context, domain, name string) (Template, error) {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + name)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	r.addParameter("active", "yes")
@@ -88,7 +88,7 @@ func (mg *MailgunImpl) UpdateTemplate(ctx context.Context, domain string, templa
 		return errors.New("UpdateTemplate() Template.Name cannot be empty")
 	}
 
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + template.Name)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + template.Name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -111,7 +111,7 @@ func (mg *MailgunImpl) UpdateTemplate(ctx context.Context, domain string, templa
 
 // Delete a template given a template name
 func (mg *MailgunImpl) DeleteTemplate(ctx context.Context, domain, name string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + name)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -131,7 +131,7 @@ type ListTemplateOptions struct {
 
 // List all available templates
 func (mg *MailgunImpl) ListTemplates(domain string, opts *ListTemplateOptions) *TemplatesIterator {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	if opts != nil {
diff --git a/template_versions.go b/template_versions.go
index f4e50c5..65b9a0b 100644
--- a/template_versions.go
+++ b/template_versions.go
@@ -24,7 +24,7 @@ type templateVersionListResp struct {
 
 // AddTemplateVersion adds a template version to a template
 func (mg *MailgunImpl) AddTemplateVersion(ctx context.Context, domain, templateName string, version *TemplateVersion) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions")
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -54,7 +54,7 @@ func (mg *MailgunImpl) AddTemplateVersion(ctx context.Context, domain, templateN
 
 // GetTemplateVersion gets a specific version of a template
 func (mg *MailgunImpl) GetTemplateVersion(ctx context.Context, domain, templateName, tag string) (TemplateVersion, error) {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -68,7 +68,7 @@ func (mg *MailgunImpl) GetTemplateVersion(ctx context.Context, domain, templateN
 
 // Update the comment and mark a version of a template active
 func (mg *MailgunImpl) UpdateTemplateVersion(ctx context.Context, domain, templateName string, version *TemplateVersion) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + version.Tag)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + version.Tag)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -94,7 +94,7 @@ func (mg *MailgunImpl) UpdateTemplateVersion(ctx context.Context, domain, templa
 
 // Delete a specific version of a template
 func (mg *MailgunImpl) DeleteTemplateVersion(ctx context.Context, domain, templateName, tag string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag)
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions/" + tag)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -109,7 +109,7 @@ type TemplateVersionsIterator struct {
 
 // ListTemplateVersions lists all the versions of a specific template
 func (mg *MailgunImpl) ListTemplateVersions(domain, templateName string, opts *ListOptions) *TemplateVersionsIterator {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions")
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, templatesEndpoint, domain) + "/" + templateName + "/versions")
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	if opts != nil {
diff --git a/unsubscribes.go b/unsubscribes.go
index 019b5c4..d76b419 100644
--- a/unsubscribes.go
+++ b/unsubscribes.go
@@ -19,7 +19,7 @@ type unsubscribesResponse struct {
 
 // Fetches the list of unsubscribes
 func (mg *MailgunImpl) ListUnsubscribes(domain string, opts *ListOptions) *UnsubscribesIterator {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, unsubscribesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, unsubscribesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	if opts != nil {
@@ -131,7 +131,7 @@ func (ci *UnsubscribesIterator) fetch(ctx context.Context, url string) error {
 
 // Retreives a single unsubscribe record. Can be used to check if a given address is present in the list of unsubscribed users.
 func (mg *MailgunImpl) GetUnsubscribe(ctx context.Context, domain, address string) (Unsubscribe, error) {
-	r := newHTTPRequest(generateApiUrlWithTarget(mg, unsubscribesEndpoint, domain, address))
+	r := newHTTPRequest(generateApiV3UrlWithTarget(mg, unsubscribesEndpoint, domain, address))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -143,7 +143,7 @@ func (mg *MailgunImpl) GetUnsubscribe(ctx context.Context, domain, address strin
 
 // Unsubscribe adds an e-mail address to the domain's unsubscription table.
 func (mg *MailgunImpl) CreateUnsubscribe(ctx context.Context, domain, address, tag string) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, unsubscribesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, unsubscribesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -155,7 +155,7 @@ func (mg *MailgunImpl) CreateUnsubscribe(ctx context.Context, domain, address, t
 
 // CreateUnsubscribes adds multiple e-mail addresses to the domain's unsubscription table.
 func (mg *MailgunImpl) CreateUnsubscribes(ctx context.Context, domain string, unsubscribes []Unsubscribe) error {
-	r := newHTTPRequest(generateApiUrlWithDomain(mg, unsubscribesEndpoint, domain))
+	r := newHTTPRequest(generateApiV3UrlWithDomain(mg, unsubscribesEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	r.addHeader("Content-Type", "application/json")
@@ -169,7 +169,7 @@ func (mg *MailgunImpl) CreateUnsubscribes(ctx context.Context, domain string, un
 // If passing in an ID (discoverable from, e.g., ListUnsubscribes()), the e-mail address associated
 // with the given ID will be removed.
 func (mg *MailgunImpl) DeleteUnsubscribe(ctx context.Context, domain, address string) error {
-	r := newHTTPRequest(generateApiUrlWithTarget(mg, unsubscribesEndpoint, domain, address))
+	r := newHTTPRequest(generateApiV3UrlWithTarget(mg, unsubscribesEndpoint, domain, address))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -180,7 +180,7 @@ func (mg *MailgunImpl) DeleteUnsubscribe(ctx context.Context, domain, address st
 // If passing in an ID (discoverable from, e.g., ListUnsubscribes()), the e-mail address associated
 // with the given ID will be removed.
 func (mg *MailgunImpl) DeleteUnsubscribeWithTag(ctx context.Context, domain, a, t string) error {
-	r := newHTTPRequest(generateApiUrlWithTarget(mg, unsubscribesEndpoint, domain, a))
+	r := newHTTPRequest(generateApiV3UrlWithTarget(mg, unsubscribesEndpoint, domain, a))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	r.addParameter("tag", t)
diff --git a/webhooks.go b/webhooks.go
index 2bbfe52..81733c9 100644
--- a/webhooks.go
+++ b/webhooks.go
@@ -30,7 +30,7 @@ type WebHookResponse struct {
 // ListWebhooks returns the complete set of webhooks configured for your domain.
 // Note that a zero-length mapping is not an error.
 func (mg *MailgunImpl) ListWebhooks(ctx context.Context, domain string) (map[string][]string, error) {
-	r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain))
+	r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 
@@ -54,7 +54,7 @@ func (mg *MailgunImpl) ListWebhooks(ctx context.Context, domain string) (map[str
 
 // CreateWebhook installs a new webhook for your domain.
 func (mg *MailgunImpl) CreateWebhook(ctx context.Context, domain, id string, urls []string) error {
-	r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain))
+	r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain))
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()
@@ -68,7 +68,7 @@ func (mg *MailgunImpl) CreateWebhook(ctx context.Context, domain, id string, url
 
 // DeleteWebhook removes the specified webhook from your domain's configuration.
 func (mg *MailgunImpl) DeleteWebhook(ctx context.Context, domain, name string) error {
-	r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name)
+	r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	_, err := makeDeleteRequest(ctx, r)
@@ -77,7 +77,7 @@ func (mg *MailgunImpl) DeleteWebhook(ctx context.Context, domain, name string) e
 
 // GetWebhook retrieves the currently assigned webhook URL associated with the provided type of webhook.
 func (mg *MailgunImpl) GetWebhook(ctx context.Context, domain, name string) ([]string, error) {
-	r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name)
+	r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	var body WebHookResponse
@@ -96,7 +96,7 @@ func (mg *MailgunImpl) GetWebhook(ctx context.Context, domain, name string) ([]s
 
 // UpdateWebhook replaces one webhook setting for another.
 func (mg *MailgunImpl) UpdateWebhook(ctx context.Context, domain, name string, urls []string) error {
-	r := newHTTPRequest(generateDomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name)
+	r := newHTTPRequest(generateV3DomainsApiUrl(mg, webhooksEndpoint, domain) + "/" + name)
 	r.setClient(mg.HTTPClient())
 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 	p := newUrlEncodedPayload()


Test patch:
diff --git a/analytics_test.go b/analytics_test.go
index abe86d9..dcb81d5 100644
--- a/analytics_test.go
+++ b/analytics_test.go
@@ -11,7 +11,8 @@ import (
 
 func TestListMetrics(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL1())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	start, _ := mailgun.NewRFC2822Time("Tue, 24 Sep 2024 00:00:00 +0000")
 	end, _ := mailgun.NewRFC2822Time("Tue, 24 Oct 2024 00:00:00 +0000")
diff --git a/attachments_test.go b/attachments_test.go
index 8e1de0a..964f8d8 100644
--- a/attachments_test.go
+++ b/attachments_test.go
@@ -27,7 +27,8 @@ func createAttachment(t *testing.T) string {
 
 func TestMultipleAttachments(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	var ctx = context.Background()
 
diff --git a/bounces_test.go b/bounces_test.go
index 048311c..9329f45 100644
--- a/bounces_test.go
+++ b/bounces_test.go
@@ -15,7 +15,8 @@ import (
 
 func TestGetBounces(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	it := mg.ListBounces(testDomain, nil)
@@ -31,12 +32,13 @@ func TestGetBounces(t *testing.T) {
 
 func TestGetSingleBounce(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	exampleEmail := fmt.Sprintf("%s@%s", strings.ToLower(randomString(64, "")),
 		os.Getenv("MG_DOMAIN"))
-	_, err := mg.GetBounce(ctx, testDomain, exampleEmail)
+	_, err = mg.GetBounce(ctx, testDomain, exampleEmail)
 	require.NotNil(t, err)
 
 	var ure *mailgun.UnexpectedResponseError
@@ -46,7 +48,9 @@ func TestGetSingleBounce(t *testing.T) {
 
 func TestAddDelBounces(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	findBounce := func(address string) bool {
@@ -71,7 +75,7 @@ func TestAddDelBounces(t *testing.T) {
 	exampleEmail := fmt.Sprintf("%s@%s", strings.ToLower(randomString(8, "bounce")), domain)
 
 	// Add the bounce for our address.
-	err := mg.AddBounce(ctx, testDomain, exampleEmail, "550", "TestAddDelBounces-generated error")
+	err = mg.AddBounce(ctx, testDomain, exampleEmail, "550", "TestAddDelBounces-generated error")
 	require.NoError(t, err)
 
 	// Give API some time to refresh cache
@@ -104,7 +108,8 @@ func TestAddDelBounces(t *testing.T) {
 
 func TestAddDelBounceList(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
diff --git a/credentials_test.go b/credentials_test.go
index 4accc29..8d81106 100644
--- a/credentials_test.go
+++ b/credentials_test.go
@@ -12,7 +12,8 @@ import (
 
 func TestGetCredentials(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	it := mg.ListCredentials(testDomain, nil)
@@ -29,7 +30,8 @@ func TestGetCredentials(t *testing.T) {
 
 func TestCreateDeleteCredentials(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	randomPassword := randomString(16, "pw")
 	randomID := strings.ToLower(randomString(16, "usr"))
diff --git a/domains_test.go b/domains_test.go
index 87388b1..c7a4fb2 100644
--- a/domains_test.go
+++ b/domains_test.go
@@ -18,7 +18,9 @@ const (
 
 func TestListDomains(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	it := mg.ListDomains(nil)
@@ -35,7 +37,9 @@ func TestListDomains(t *testing.T) {
 
 func TestGetSingleDomain(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	it := mg.ListDomains(nil)
@@ -59,10 +63,11 @@ func TestGetSingleDomain(t *testing.T) {
 
 func TestGetSingleDomainNotExist(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
-	_, err := mg.GetDomain(ctx, "unknown.domain")
+	_, err = mg.GetDomain(ctx, "unknown.domain")
 	if err == nil {
 		t.Fatal("Did not expect a domain to exist")
 	}
@@ -73,11 +78,13 @@ func TestGetSingleDomainNotExist(t *testing.T) {
 
 func TestAddUpdateDeleteDomain(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	// First, we need to add the domain.
-	_, err := mg.CreateDomain(ctx, "mx.mailgun.test",
+	_, err = mg.CreateDomain(ctx, "mx.mailgun.test",
 		&mailgun.CreateDomainOptions{SpamAction: mailgun.SpamActionTag, Password: "supersecret", WebScheme: "http"})
 	require.NoError(t, err)
 
@@ -92,7 +99,9 @@ func TestAddUpdateDeleteDomain(t *testing.T) {
 
 func TestDomainConnection(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	info, err := mg.GetDomainConnection(ctx, testDomain)
@@ -113,7 +122,9 @@ func TestDomainConnection(t *testing.T) {
 
 func TestDomainTracking(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	info, err := mg.GetDomainTracking(ctx, testDomain)
@@ -154,38 +165,46 @@ func TestDomainTracking(t *testing.T) {
 
 func TestDomainVerify(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
-	_, err := mg.VerifyDomain(ctx, testDomain)
+	_, err = mg.VerifyDomain(ctx, testDomain)
 	require.NoError(t, err)
 }
 
 func TestDomainVerifyAndReturn(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
-	_, err := mg.VerifyAndReturnDomain(ctx, testDomain)
+	_, err = mg.VerifyAndReturnDomain(ctx, testDomain)
 	require.NoError(t, err)
 }
 
 func TestDomainDkimSelector(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	// Update Domain DKIM selector
-	err := mg.UpdateDomainDkimSelector(ctx, testDomain, "gotest")
+	err = mg.UpdateDomainDkimSelector(ctx, testDomain, "gotest")
 	require.NoError(t, err)
 }
 
 func TestDomainTrackingWebPrefix(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	// Update Domain Tracking Web Prefix
-	err := mg.UpdateDomainTrackingWebPrefix(ctx, testDomain, "gotest")
+	err = mg.UpdateDomainTrackingWebPrefix(ctx, testDomain, "gotest")
 	require.NoError(t, err)
 }
diff --git a/email_validation_test.go b/email_validation_test.go
index 53d4c0c..2049bd1 100644
--- a/email_validation_test.go
+++ b/email_validation_test.go
@@ -13,7 +13,8 @@ import (
 func TestEmailValidationV4(t *testing.T) {
 	v := mailgun.NewEmailValidator(testKey)
 	// API Base is set to `http://server/v4`
-	v.SetAPIBase(server.URL4())
+	v.SetAPIBase(server.URL())
+
 	ctx := context.Background()
 
 	ev, err := v.ValidateEmail(ctx, "foo@mailgun.com", false)
diff --git a/events_test.go b/events_test.go
index 6589c09..f89b389 100644
--- a/events_test.go
+++ b/events_test.go
@@ -14,7 +14,8 @@ import (
 
 func TestEventIteratorGetNext(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	it := mg.ListEvents(testDomain, &mailgun.ListEventOptions{Limit: 5})
 
@@ -63,7 +64,8 @@ func TestEventIteratorGetNext(t *testing.T) {
 
 func TestEventPoller(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	// Very short poll interval
 	it := mg.PollEvents(testDomain, &mailgun.ListEventOptions{
@@ -113,7 +115,7 @@ func TestEventPoller(t *testing.T) {
 
 func ExampleMailgunImpl_ListEvents() {
 	mg := mailgun.NewMailgun("your-api-key")
-	mg.SetAPIBase(server.URL3())
+	_ = mg.SetAPIBase(server.URL())
 
 	it := mg.ListEvents("your-domain.com", &mailgun.ListEventOptions{Limit: 100})
 
diff --git a/exports_test.go b/exports_test.go
index 0fe9cf6..6554a63 100644
--- a/exports_test.go
+++ b/exports_test.go
@@ -11,7 +11,8 @@ import (
 
 func TestExports(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	list, err := mg.ListExports(ctx, "")
@@ -38,7 +39,8 @@ func TestExports(t *testing.T) {
 
 func TestExportsLink(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	url, err := mg.GetExportLink(ctx, "12")
diff --git a/ips_test.go b/ips_test.go
index fa4fd03..6e28208 100644
--- a/ips_test.go
+++ b/ips_test.go
@@ -21,7 +21,8 @@ func TestMain(m *testing.M) {
 
 func TestListIPS(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	list, err := mg.ListIPS(ctx, false)
@@ -38,10 +39,11 @@ func TestListIPS(t *testing.T) {
 
 func TestDomainIPS(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
-	err := mg.AddDomainIP(ctx, testDomain, "192.172.1.1")
+	err = mg.AddDomainIP(ctx, testDomain, "192.172.1.1")
 	require.NoError(t, err)
 
 	list, err := mg.ListDomainIPS(ctx, testDomain)
diff --git a/limits_test.go b/limits_test.go
index 32642ad..7204704 100644
--- a/limits_test.go
+++ b/limits_test.go
@@ -11,7 +11,8 @@ import (
 
 func TestLimits(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	limits, err := mg.GetTagLimits(ctx, testDomain)
diff --git a/mailgun_test.go b/mailgun_test.go
index d3ff512..6f2647b 100644
--- a/mailgun_test.go
+++ b/mailgun_test.go
@@ -1,9 +1,7 @@
 package mailgun_test
 
 import (
-	"context"
 	"encoding/json"
-	"fmt"
 	"net/http"
 	"net/http/httptest"
 	"testing"
@@ -29,11 +27,8 @@ func TestMailgun(t *testing.T) {
 
 func TestInvalidBaseAPI(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase("https://localhost")
-
-	ctx := context.Background()
-	_, err := mg.GetDomain(ctx, "unknown.domain")
-	assert.EqualError(t, err, `APIBase must end with a /v1, /v2, /v3 or /v4; SetAPIBase("https://host/v3")`)
+	err := mg.SetAPIBase("https://localhost/v3")
+	assert.EqualError(t, err, `APIBase must not contain a version; SetAPIBase("https://host")`)
 }
 
 func TestValidBaseAPI(t *testing.T) {
@@ -47,17 +42,17 @@ func TestValidBaseAPI(t *testing.T) {
 	}))
 
 	apiBases := []string{
-		fmt.Sprintf("%s/v3", testServer.URL),
-		fmt.Sprintf("%s/proxy/v3", testServer.URL),
+		mailgun.APIBase,
+		mailgun.APIBaseEU,
+		testServer.URL,
 	}
 
 	for _, apiBase := range apiBases {
-		mg := mailgun.NewMailgun(testKey)
-		mg.SetAPIBase(apiBase)
-
-		ctx := context.Background()
-		_, err := mg.GetDomain(ctx, "unknown.domain")
-		require.NoError(t, err)
+		t.Run(apiBase, func(t *testing.T) {
+			mg := mailgun.NewMailgun(testKey)
+			err := mg.SetAPIBase(apiBase)
+			require.NoError(t, err)
+		})
 	}
 }
 
diff --git a/mailing_lists_test.go b/mailing_lists_test.go
index 4d27cdc..03aead8 100644
--- a/mailing_lists_test.go
+++ b/mailing_lists_test.go
@@ -12,11 +12,12 @@ import (
 
 func TestMailingListMembers(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	address := randomEmail("list", testDomain)
-	_, err := mg.CreateMailingList(ctx, mailgun.MailingList{
+	_, err = mg.CreateMailingList(ctx, mailgun.MailingList{
 		Address:     address,
 		Name:        address,
 		Description: "TestMailingListMembers-related mailing list",
@@ -96,7 +97,9 @@ func TestMailingListMembers(t *testing.T) {
 
 func TestMailingLists(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	address := randomEmail("list", testDomain)
@@ -119,7 +122,7 @@ func TestMailingLists(t *testing.T) {
 		return count
 	}
 
-	_, err := mg.CreateMailingList(ctx, protoList)
+	_, err = mg.CreateMailingList(ctx, protoList)
 	require.NoError(t, err)
 	defer func() {
 		require.NoError(t, mg.DeleteMailingList(ctx, address))
@@ -152,11 +155,13 @@ func TestMailingLists(t *testing.T) {
 
 func TestListMailingListRegression(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 	address := "test@example.com"
 
-	_, err := mg.CreateMailingList(ctx, mailgun.MailingList{
+	_, err = mg.CreateMailingList(ctx, mailgun.MailingList{
 		Address:     address,
 		Name:        "paging",
 		Description: "Test paging",
diff --git a/messages_test.go b/messages_test.go
index aae656c..626d8e6 100644
--- a/messages_test.go
+++ b/messages_test.go
@@ -305,12 +305,15 @@ func TestSendMGOffline(t *testing.T) {
 		assert.Equal(t, exampleText, req.FormValue("text"))
 		assert.Equal(t, toUser, req.FormValue("to"))
 		rsp := fmt.Sprintf(`{"message":"%s", "id":"%s"}`, exampleMessage, exampleID)
-		fmt.Fprint(w, rsp)
+		_, err := fmt.Fprint(w, rsp)
+		require.NoError(t, err)
 	}))
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser)
@@ -343,7 +346,8 @@ func TestSendMGSeparateDomain(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser)
@@ -397,10 +401,11 @@ func TestSendMGMessageVariables(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser)
-	err := m.AddVariable(exampleStrVarKey, exampleStrVarVal)
+	err = m.AddVariable(exampleStrVarKey, exampleStrVarVal)
 	require.NoError(t, err)
 	err = m.AddVariable(exampleBoolVarKey, false)
 	require.NoError(t, err)
@@ -469,10 +474,12 @@ func TestSendDomainError(t *testing.T) {
 	for _, c := range cases {
 		ctx := context.Background()
 		mg := mailgun.NewMailgun(exampleAPIKey)
-		mg.SetAPIBase(srv.URL + "/v3")
+		err := mg.SetAPIBase(srv.URL)
+		require.NoError(t, err)
+
 		m := mailgun.NewMessage(c.domain, fromUser, exampleSubject, exampleText, "test@test.com")
 
-		_, _, err := mg.Send(ctx, m)
+		_, _, err = mg.Send(ctx, m)
 		if c.isValid {
 			require.NoError(t, err)
 		} else {
@@ -494,10 +501,11 @@ func TestSendEOFError(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser)
-	_, _, err := mg.Send(context.Background(), m)
+	_, _, err = mg.Send(context.Background(), m)
 	require.NotNil(t, err)
 	// TODO(vtopc): do not compare strings, use errors.Is or errors.As:
 	require.Contains(t, err.Error(), "remote server prematurely closed connection: Post ")
@@ -519,11 +527,12 @@ func TestHasRecipient(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 
 	// No recipient
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText)
-	_, _, err := mg.Send(context.Background(), m)
+	_, _, err = mg.Send(context.Background(), m)
 	require.EqualError(t, err, "message not valid")
 
 	// Provided Bcc
@@ -558,9 +567,10 @@ func TestResendStored(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 
-	_, _, err := mg.ReSend(context.Background(), srv.URL+"/v3/some-url")
+	_, _, err = mg.ReSend(context.Background(), srv.URL+"/v3/some-url")
 	require.NotNil(t, err)
 	require.EqualError(t, err, "must provide at least one recipient")
 
@@ -590,7 +600,8 @@ func TestAddOverrideHeader(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 	mg.AddOverrideHeader("Host", "example.com")
 	mg.AddOverrideHeader("CustomHeader", "custom-value")
 	ctx := context.Background()
@@ -626,7 +637,8 @@ func TestOnBehalfOfSubaccount(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
 	mg.AddOverrideHeader("Host", "example.com")
 	mg.AddOverrideHeader("CustomHeader", "custom-value")
 	mg.SetOnBehalfOfSubaccount("mailgun.subaccount")
@@ -665,7 +677,9 @@ func TestSendTLSOptions(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, exampleText, toUser)
@@ -695,7 +709,9 @@ func TestSendTemplate(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, "", toUser)
@@ -728,7 +744,9 @@ func TestSendTemplateOptions(t *testing.T) {
 	defer srv.Close()
 
 	mg := mailgun.NewMailgun(exampleAPIKey)
-	mg.SetAPIBase(srv.URL + "/v3")
+	err := mg.SetAPIBase(srv.URL)
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	m := mailgun.NewMessage(exampleDomain, fromUser, exampleSubject, "", toUser)
diff --git a/routes_test.go b/routes_test.go
index 6b6eea1..7b8a20a 100644
--- a/routes_test.go
+++ b/routes_test.go
@@ -11,7 +11,8 @@ import (
 
 func TestRouteCRUD(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	var countRoutes = func() int {
@@ -59,7 +60,8 @@ func TestRouteCRUD(t *testing.T) {
 
 func TestRoutesIterator(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	it := mg.ListRoutes(&mailgun.ListOptions{Limit: 2})
 
diff --git a/spam_complaints_test.go b/spam_complaints_test.go
index 9f85d75..d0edac5 100644
--- a/spam_complaints_test.go
+++ b/spam_complaints_test.go
@@ -12,7 +12,8 @@ import (
 
 func TestGetComplaints(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
@@ -25,10 +26,12 @@ func TestGetComplaints(t *testing.T) {
 
 func TestGetComplaintFromRandomNoComplaint(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
-	_, err := mg.GetComplaint(ctx, testDomain, randomString(64, "")+"@example.com")
+	_, err = mg.GetComplaint(ctx, testDomain, randomString(64, "")+"@example.com")
 	require.NotNil(t, err)
 
 	var ure *mailgun.UnexpectedResponseError
@@ -38,7 +41,9 @@ func TestGetComplaintFromRandomNoComplaint(t *testing.T) {
 
 func TestCreateDeleteComplaint(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	var hasComplaint = func(email string) bool {
@@ -69,7 +74,9 @@ func TestCreateDeleteComplaint(t *testing.T) {
 
 func TestCreateDeleteComplaintList(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	var hasComplaint = func(email string) bool {
diff --git a/storage_test.go b/storage_test.go
index cd00dc0..249671b 100644
--- a/storage_test.go
+++ b/storage_test.go
@@ -14,7 +14,8 @@ import (
 
 func TestStorage(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	var ctx = context.Background()
 
diff --git a/subaccounts_test.go b/subaccounts_test.go
index acd14a5..5a76ba2 100644
--- a/subaccounts_test.go
+++ b/subaccounts_test.go
@@ -18,7 +18,8 @@ const (
 
 func TestListSubaccounts(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	iterator := mg.ListSubaccounts(nil)
 	require.NotNil(t, iterator)
@@ -38,7 +39,8 @@ func TestListSubaccounts(t *testing.T) {
 
 func TestSubaccountDetails(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
@@ -56,11 +58,12 @@ func TestSubaccountDetails(t *testing.T) {
 
 func TestSubaccountDetailsStatusNotFound(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
-	_, err := mg.SubaccountDetails(ctx, "unexisting.id")
+	_, err = mg.SubaccountDetails(ctx, "unexisting.id")
 	if err == nil {
 		t.Fatal("Did not expect a subaccount to exist")
 	}
@@ -71,7 +74,8 @@ func TestSubaccountDetailsStatusNotFound(t *testing.T) {
 
 func TestCreateSubaccount(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
@@ -82,17 +86,19 @@ func TestCreateSubaccount(t *testing.T) {
 
 func TestEnableSubaccountAlreadyEnabled(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
-	_, err := mg.EnableSubaccount(ctx, testEnabledSubaccountId)
+	_, err = mg.EnableSubaccount(ctx, testEnabledSubaccountId)
 	require.NoError(t, err)
 }
 
 func TestEnableSubaccount(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
@@ -103,7 +109,8 @@ func TestEnableSubaccount(t *testing.T) {
 
 func TestDisableSubaccount(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
@@ -114,10 +121,11 @@ func TestDisableSubaccount(t *testing.T) {
 
 func TestDisableSubaccountAlreadyDisabled(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 
-	_, err := mg.DisableSubaccount(ctx, testDisabledSubaccountId)
+	_, err = mg.DisableSubaccount(ctx, testDisabledSubaccountId)
 	require.NoError(t, err)
 }
diff --git a/tags_test.go b/tags_test.go
index 50e4b31..9d890b0 100644
--- a/tags_test.go
+++ b/tags_test.go
@@ -19,7 +19,9 @@ const (
 
 func TestTags(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	msg := mailgun.NewMessage(testDomain, fromUser, exampleSubject, exampleText, "test@example.com")
 	require.NoError(t, msg.AddTag("newsletter"))
 	require.NoError(t, msg.AddTag("homer"))
@@ -29,7 +31,7 @@ func TestTags(t *testing.T) {
 
 	ctx := context.Background()
 	// Create an email with some tags attached
-	_, _, err := mg.Send(ctx, msg)
+	_, _, err = mg.Send(ctx, msg)
 	require.NoError(t, err)
 
 	// Wait for the tag to show up
@@ -87,7 +89,9 @@ func waitForTag(mg mailgun.Mailgun, tag string) error {
 
 func TestDeleteTag(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	require.NoError(t, mg.DeleteTag(ctx, testDomain, "newsletter"))
diff --git a/template_test.go b/template_test.go
index 28cb6dd..0fbf3de 100644
--- a/template_test.go
+++ b/template_test.go
@@ -14,7 +14,9 @@ import (
 
 func TestTemplateCRUD(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	findTemplate := func(name string) bool {
diff --git a/template_versions_test.go b/template_versions_test.go
index f6c8467..39c1adf 100644
--- a/template_versions_test.go
+++ b/template_versions_test.go
@@ -11,7 +11,9 @@ import (
 
 func TestTemplateVersionsCRUD(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	findVersion := func(templateName, tag string) bool {
diff --git a/unsubscribes_test.go b/unsubscribes_test.go
index 7787f9d..deb04f6 100644
--- a/unsubscribes_test.go
+++ b/unsubscribes_test.go
@@ -11,7 +11,8 @@ import (
 
 func TestCreateUnsubscriber(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	email := randomEmail("unsubcribe", os.Getenv("MG_DOMAIN"))
 	ctx := context.Background()
@@ -31,7 +32,9 @@ func TestCreateUnsubscribes(t *testing.T) {
 		},
 	}
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	// Create unsubscription records
@@ -40,7 +43,9 @@ func TestCreateUnsubscribes(t *testing.T) {
 
 func TestListUnsubscribes(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
+
 	ctx := context.Background()
 
 	it := mg.ListUnsubscribes(testDomain, nil)
@@ -59,7 +64,8 @@ func TestListUnsubscribes(t *testing.T) {
 
 func TestGetUnsubscribe(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	email := randomEmail("unsubcribe", os.Getenv("MG_DOMAIN"))
 
@@ -78,7 +84,8 @@ func TestGetUnsubscribe(t *testing.T) {
 
 func TestCreateDestroyUnsubscription(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	email := randomEmail("unsubcribe", os.Getenv("MG_DOMAIN"))
 
@@ -87,7 +94,7 @@ func TestCreateDestroyUnsubscription(t *testing.T) {
 	// Create unsubscription record
 	require.NoError(t, mg.CreateUnsubscribe(ctx, testDomain, email, "*"))
 
-	_, err := mg.GetUnsubscribe(ctx, testDomain, email)
+	_, err = mg.GetUnsubscribe(ctx, testDomain, email)
 	require.NoError(t, err)
 
 	// Destroy the unsubscription record
diff --git a/webhooks_test.go b/webhooks_test.go
index c7aa2d2..9f73aa6 100644
--- a/webhooks_test.go
+++ b/webhooks_test.go
@@ -20,7 +20,8 @@ import (
 
 func TestGetWebhook(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	list, err := mg.ListWebhooks(ctx, testDomain)
@@ -35,7 +36,8 @@ func TestGetWebhook(t *testing.T) {
 
 func TestWebhookCRUD(t *testing.T) {
 	mg := mailgun.NewMailgun(testKey)
-	mg.SetAPIBase(server.URL3())
+	err := mg.SetAPIBase(server.URL())
+	require.NoError(t, err)
 
 	ctx := context.Background()
 	list, err := mg.ListWebhooks(ctx, testDomain)