pipedrive-go

module
v1.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2026 License: MIT

README

pipedrive-go

Go Report Card Coverage Status

Go SDK for the Pipedrive API with a handwritten, stable public surface.

  • API v2: full support
  • API v1: legacy-only (endpoints not present in v2)

Generated OpenAPI clients are internal-only; use the pipedrive/v1 and pipedrive/v2 packages.

API versions

This SDK is v2-first. Use pipedrive/v2 for new work and only reach for pipedrive/v1 when an endpoint is not available in v2. The v1 surface is derived from the v1 OpenAPI spec with all v2-covered operations removed, so endpoints migrate out of v1 automatically as v2 grows.

Endpoint tables:

  • v2: docs/endpoints-v2.md
  • v1 legacy: docs/endpoints-v1-legacy.md

Install

go get github.com/juhokoskela/pipedrive-go@latest

Go 1.25+ is required.

The repository prefers Go 1.26.5 locally via the toolchain directive in go.mod.

To pin a specific version:

go get github.com/juhokoskela/pipedrive-go@v1.0.8

Quickstart (API token)

v2:

package main

import (
	"context"
	"log"

	"github.com/juhokoskela/pipedrive-go/pipedrive"
	v2 "github.com/juhokoskela/pipedrive-go/pipedrive/v2"
)

func main() {
	client, err := v2.NewClient(pipedrive.Config{
		Auth: pipedrive.APITokenAuth("YOUR_API_TOKEN"),
	})
	if err != nil {
		log.Fatal(err)
	}

	pipelines, _, err := client.Pipelines.List(
		context.Background(),
		v2.WithPipelinesPageSize(50),
	)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("pipelines=%d", len(pipelines))
}

v1 legacy:

client, err := v1.NewClient(pipedrive.Config{
	Auth: pipedrive.APITokenAuth("YOUR_API_TOKEN"),
})
if err != nil {
	log.Fatal(err)
}

currencies, err := client.Currencies.List(context.Background(), v1.ListCurrenciesRequest{})
if err != nil {
	log.Fatal(err)
}
log.Printf("currencies=%d", len(currencies))

Pagination

Cursor pagination helpers are exposed as ListPager and ForEach:

pager := client.Deals.ListPager(v2.WithDealsPageSize(100))
err := pager.ForEach(context.Background(), func(d v2.Deal) error {
	log.Printf("deal id=%d title=%s", d.ID, d.Title)
	return nil
})
if err != nil {
	log.Fatal(err)
}

OAuth2

Use the v1 OAuth helper to build the authorize URL and exchange tokens, then pass the access token into a v2 client.

import (
	"context"
	"encoding/base64"
	"log"

	"golang.org/x/oauth2"

	"github.com/juhokoskela/pipedrive-go/pipedrive"
	v1 "github.com/juhokoskela/pipedrive-go/pipedrive/v1"
	v2 "github.com/juhokoskela/pipedrive-go/pipedrive/v2"
)

ctx := context.Background()
oauthClient, _ := v1.NewClient(pipedrive.Config{})

authURL, err := oauthClient.OAuth.Authorize(
	ctx,
	v1.WithOAuthClientID(clientID),
	v1.WithOAuthRedirectURI(redirectURI),
	v1.WithOAuthState("state123"),
)
if err != nil {
	log.Fatal(err)
}
log.Printf("open: %s", authURL)

authHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(clientID+":"+clientSecret))
tokens, err := oauthClient.OAuth.GetTokens(
	ctx,
	v1.WithOAuthAuthorization(authHeader),
	v1.WithOAuthCode(code),
	v1.WithOAuthRedirectURI(redirectURI),
)
if err != nil {
	log.Fatal(err)
}

ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: tokens.AccessToken})
apiClient, _ := v2.NewClient(pipedrive.Config{
	BaseURL: tokens.APIDomain + "/api/v2",
	Auth:    pipedrive.OAuth2Auth{TokenSource: ts},
})

Retries and per-request options

Retries are enabled by default for 429/502/503/504 with backoff and jitter. Override globally with RetryPolicy, or per call with request options:

policy := pipedrive.DefaultRetryPolicy()
policy.MaxAttempts = 2

client, _ := v2.NewClient(pipedrive.Config{
	Auth:        pipedrive.APITokenAuth("YOUR_API_TOKEN"),
	RetryPolicy: &policy,
})

deal, err := client.Deals.Get(
	context.Background(),
	v2.DealID(123),
	v2.WithDealRequestOptions(pipedrive.WithNoRetry()),
)

Response bodies are capped at 64 MiB by default. Override globally with Config.MaxResponseSize, per request with WithResponseSizeLimit or WithNoResponseSizeLimit, and use client.Files.DownloadTo to stream large v1 file downloads.

Custom HTTP and middleware

client, _ := v2.NewClient(pipedrive.Config{
	Auth:       pipedrive.APITokenAuth("YOUR_API_TOKEN"),
	HTTPClient: customClient,
	Middleware: []pipedrive.Middleware{loggingMiddleware},
	UserAgent:  "my-app/1.0",
})

Request options such as WithHeader and WithRequestEditor run before the transport chain. If you set Authorization or x-api-token yourself, the configured auth provider will not overwrite that header, and custom middleware can also replace auth headers later in the chain.

Raw API escape hatch

import "net/http"

var out struct {
	Data []v2.Pipeline `json:"data"`
}
err := client.Raw.Do(context.Background(), http.MethodGet, "/pipelines", nil, nil, &out)

Known API quirks

  • Products category is documented as a numeric option ID on write, but some responses return a string label. The v2 SDK tolerates both; string labels are exposed via Product.CategoryName, while numeric IDs remain in Product.Category.

Integration checks

Opt-in integration tests (skipped by default):

PIPEDRIVE_API_TOKEN=... go test ./pipedrive -run Integration -v
PIPEDRIVE_API_TOKEN=... PIPEDRIVE_INTEGRATION_WRITE=1 go test ./pipedrive -run IntegrationV2OrganizationCreateDelete -v

Smoke CLI:

PIPEDRIVE_API_TOKEN=... go run ./cmd/smoke

Optional env overrides:

  • PIPEDRIVE_BASE_URL_V1
  • PIPEDRIVE_BASE_URL_V2
  • PIPEDRIVE_SMOKE_TIMEOUT

Examples

See the runnable examples in examples/:

  • examples/token for API token usage
  • examples/oauth for OAuth2 usage

Versioning

The module follows semantic versioning and does not encode Pipedrive API versioning in the module path. The v1/v2 distinction is in the package path, not the module version. See RELEASING.md for release steps.

Development

make update-specs
make derive-v1-legacy
make generate
make docs
make fmt
make lint
make security
go test ./...

Directories

Path Synopsis
cmd
endpoint-docs command
smoke command
examples
oauth command
token command
internal
gen/v1
Package v1 provides primitives to interact with the openapi HTTP API.
Package v1 provides primitives to interact with the openapi HTTP API.
gen/v2
Package v2 provides primitives to interact with the openapi HTTP API.
Package v2 provides primitives to interact with the openapi HTTP API.
v1
v2

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL