Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cursor/rules/cloudinary.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
description: Cloudinary cloudinary-go — agent guide
alwaysApply: true
---

Read and follow `AGENTS.md` in the repository root. It is the single
authoritative guide for this package: build/test commands, conventions,
gotchas, and when to use this SDK versus a sibling Cloudinary package.
5 changes: 5 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Cloudinary cloudinary-go — instructions for AI coding agents

Read `AGENTS.md` in the repository root and follow it. It is the single
authoritative guide for this package: build/test commands, conventions,
gotchas, and when to use this SDK versus a sibling Cloudinary package.
81 changes: 81 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# AGENTS.md — cloudinary-go

## What this package is (one line)
Official Cloudinary Go **server-side** SDK: upload assets, build transformation/delivery URLs, and call the Admin API from your backend — the SDK that holds your `API_SECRET`.

## When to use this / when NOT to use this
- **Use this when:** you are in a Go server runtime (HTTP handlers, workers, CLIs, build scripts) and need to upload assets, sign delivery URLs, or administer assets — anything that requires the `API_SECRET` to stay off the client.
- **Do NOT use this when:** you only need the **AI Content Analysis API** as a focused typed client → use [`analysis-go`](https://github.com/cloudinary/analysis-go); or you're doing **account provisioning** (sub-accounts, users, access keys) → use [`account-provisioning-go`](https://github.com/cloudinary/account-provisioning-go); or you want a no-code/autonomous-agent path → use the Cloudinary MCP server.
- **Sibling packages:** `analysis-go` and `account-provisioning-go` are narrow clients for a single API surface. This package is the **full server SDK** (upload + transform URLs + Admin API together) and is the default for general Cloudinary work in Go.

## Setup
```bash
go get github.com/cloudinary/cloudinary-go/v2
```
Required configuration / credentials:
```bash
export CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME
```
`cloudinary.New()` reads `CLOUDINARY_URL` from the environment automatically.

## Minimal runnable example
```go
package main

import (
"context"
"fmt"

"github.com/cloudinary/cloudinary-go/v2"
"github.com/cloudinary/cloudinary-go/v2/api/uploader"
)

func main() {
cld, _ := cloudinary.New() // reads CLOUDINARY_URL
ctx := context.Background()

resp, _ := cld.Upload.Upload(ctx, "my_picture.jpg", uploader.UploadParams{})
fmt.Println(resp.SecureURL)

image, _ := cld.Image("sample.jpg")
image.Transformation = "c_fill,h_150,w_100"
url, _ := image.String()
fmt.Println(url)
}
```

## Build / test commands (run these after editing)
```bash
go mod download # fetch dependencies
go build ./... # compile everything
go test ./... # run the suite (CI uses gotestsum ./..., equivalent)
go vet ./... # static checks
```
Notes:
- **Tests need `CLOUDINARY_URL`** — much of the suite hits the live Upload/Admin APIs, so set it to a real (test) cloud before running. CI allocates one via `scripts/get_test_cloud.sh`; locally, export your own. See `TEST.md` for test-writing conventions.
- If you edit param/option structs, regenerate fluent setters: `make generate`. Don't hand-edit generated `*_setters.go` files.
- CI (`.github/workflows/test.yaml`) matrix runs Go 1.20–1.24, tests only (via `gotestsum`). There is no golangci-lint step and no `.golangci.yml` in the repo — `go vet` and `gofmt` are the de-facto gate.

## Conventions & gotchas
- **The `/v2` import path is mandatory.** Module is `github.com/cloudinary/cloudinary-go/v2`; importing without `/v2` resolves to the unmaintained 1.x and will not compile against current code.
- Format with `gofmt` / `go fmt ./...` before committing.
- Public entry point is the `cloudinary` package (`cloudinary.New()`); upload lives under `api/uploader`, admin under `api/admin`. Import these subpackages explicitly rather than reaching into deep internal paths.
- Generated setters: edit the generator under `gen/generate_setters/`, not the output. Run `make generate` after changing option structs.
- Signed uploads and the Admin API require the `API_SECRET` — keep it server-side; never embed it in a client binary or browser bundle.
- **Version support:** SDK 2.8+ requires **Go 1.20+**; SDK 2.7 / 1.x support Go 1.13–1.19. See the table in `README.md`.

## Canonical docs (leave the repo for depth)
- Go SDK guide: https://cloudinary.com/documentation/go_integration
- Transformations: https://cloudinary.com/documentation/go_media_transformations
- Upload: https://cloudinary.com/documentation/go_image_and_video_upload
- Admin API: https://cloudinary.com/documentation/go_asset_administration
- API reference (pkg.go.dev): https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2
- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers

## Agent / MCP note
If the capability you need is also exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for generated Go code. See cloudinary/mcp-servers.

## Commit / PR conventions
- Branch off `main`; rebase on `upstream/main` before opening a PR (see `CONTRIBUTING.md`).
- PR description must clearly state the bug/feature and reference the related issue number.
- Provide tests covering new code (`TEST.md`), and ensure CI tests pass before requesting review.
27 changes: 27 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@AGENTS.md

# CLAUDE.md — cloudinary-go

## What this repo is

Official Cloudinary Go **server-side** SDK: upload assets, build transformation/delivery URLs, and call the Admin API from backend code. Module path: `github.com/cloudinary/cloudinary-go/v2` (the `/v2` suffix is mandatory — dropping it resolves to the unmaintained 1.x line).

## Key constraints / gotchas

- **`/v2` import path is mandatory.** Import `github.com/cloudinary/cloudinary-go/v2` everywhere; subpackages are `api/uploader` and `api/admin`.
- **`API_SECRET` stays server-side.** Never embed it in a client binary or browser bundle; use the signed-upload pattern for browser-direct flows.
- **Tests need `CLOUDINARY_URL`.** Most of the suite hits the live Upload/Admin APIs; set `export CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME` before running. CI uses `scripts/get_test_cloud.sh`.
- **Do not hand-edit `*_setters.go` files.** They are generated. Edit the generator under `gen/generate_setters/`, then run `make generate`.
- **Go floor:** SDK 2.8+ requires Go 1.20+. SDK 2.7 / 1.x support Go 1.13–1.19.
- **CI gate:** `.github/workflows/test.yaml` runs `gotestsum ./...` on Go 1.20–1.24. There is no golangci-lint step; `go vet` and `gofmt` are the de-facto gate.
- **Format before committing:** `go fmt ./...`

## Verified build / test commands

```bash
go mod download # fetch dependencies
go build ./... # compile everything
go vet ./... # static checks
go test ./... # full suite (requires CLOUDINARY_URL pointing at a real test cloud)
make generate # regenerate fluent setters after editing param/option structs
```
214 changes: 121 additions & 93 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,137 +1,165 @@
[![Tests](https://github.com/cloudinary/cloudinary-go/actions/workflows/test.yaml/badge.svg)](https://github.com/cloudinary/cloudinary-go/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/cloudinary/cloudinary-go/v2)](https://goreportcard.com/report/github.com/cloudinary/cloudinary-go/v2)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/cloudinary/cloudinary-go/v2)](https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2)

Cloudinary Go SDK
==================

## About

The Cloudinary Go SDK allows you to quickly and easily integrate your application with Cloudinary.
Effortlessly optimize, transform, upload and manage your cloud's assets.

#### Note
# Cloudinary Go SDK

This Readme provides basic installation and usage information.
For the complete documentation, see the [Go SDK Guide](https://cloudinary.com/documentation/go_integration).

## Table of Contents

- [Key Features](#key-features)
- [Version Support](#Version-Support)
- [Installation](#installation)
- [Usage](#usage)
- [Setup](#Setup)
- [Transform and Optimize Assets](#Transform-and-Optimize-Assets)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/cloudinary/cloudinary-go/v2)](https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2)
[![License](https://img.shields.io/github/license/cloudinary/cloudinary-go)](https://github.com/cloudinary/cloudinary-go/blob/main/LICENSE)
[![Tests](https://github.com/cloudinary/cloudinary-go/actions/workflows/test.yaml/badge.svg)](https://github.com/cloudinary/cloudinary-go/actions/workflows/test.yaml)

## Key Features
The Cloudinary Go SDK is the server-side SDK for Go. Use it to upload assets, build transformation and delivery URLs, and call the Admin API from backend code. The module path is `github.com/cloudinary/cloudinary-go/v2` (the `/v2` suffix is required); SDK 2.8 and later require Go 1.20 or later.

- [Transform](https://cloudinary.com/documentation/go_media_transformations) assets.
- [Asset Management](https://cloudinary.com/documentation/go_asset_administration).
- [Secure URLs](https://cloudinary.com/documentation/video_manipulation_and_delivery#generating_secure_https_urls_using_sdks).
## Installation

## Version Support
```bash
go get github.com/cloudinary/cloudinary-go/v2
```

| **SDK Version** | **Go 1.13 - 1.19** | **Go 1.20** | **Go 1.21** | **Go 1.22** | **Go 1.23** |
|-----------------|--------------------|-------------|-------------|-------------|-------------|
| **2.8 & Up** | ❌ | ✔️ | ✔️ | ✔️ | ✔️ |
| **2.7** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| **1.x** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
## Configuration

## Installation
The SDK reads credentials from the `CLOUDINARY_URL` environment variable:

```bash
go get github.com/cloudinary/cloudinary-go/v2
export CLOUDINARY_URL=cloudinary://<API_KEY>:<API_SECRET>@<CLOUD_NAME>
```

# Usage
```go
import "github.com/cloudinary/cloudinary-go/v2"

cld, err := cloudinary.New() // reads CLOUDINARY_URL from the environment
```

### Setup
To pass credentials in code instead, use `NewFromParams`:

```go
import (
"github.com/cloudinary/cloudinary-go/v2"
)
import "github.com/cloudinary/cloudinary-go/v2"

cld, _ := cloudinary.New()
cld, err := cloudinary.NewFromParams("my_cloud_name", "my_key", "my_secret")
```

- [See full documentation](https://cloudinary.com/documentation/go_integration#configuration).
`New`, `NewFromParams`, and `NewFromURL` all return an error when the credentials are missing or malformed — check it. Keep the API secret on the server: don't put it in a distributed binary, client-side code, or version control.

### Transform and Optimize Assets
## Quick examples

- [See full documentation](https://cloudinary.com/documentation/go_media_transformations).
### Upload a file

`cld.Upload.Upload(ctx, file, uploader.UploadParams{...})` returns a `*uploader.UploadResult`. The `file` argument accepts a local path, a remote URL, a base64 string, an `*os.File`, a `*multipart.FileHeader`, or any `io.Reader`. The result includes `PublicID` and `SecureURL`:

```go
image, err := cld.Image("sample.jpg")
if err != nil {...}
package main

import (
"context"
"fmt"
"log"

image.Transformation = "c_fill,h_150,w_100"
"github.com/cloudinary/cloudinary-go/v2"
"github.com/cloudinary/cloudinary-go/v2/api/uploader"
)

imageURL, err := image.String()
func main() {
cld, err := cloudinary.New() // reads CLOUDINARY_URL from the environment
if err != nil {
log.Fatal(err)
}

resp, err := cld.Upload.Upload(context.Background(), "my_image.jpg", uploader.UploadParams{
PublicID: "cms/hero", // optional: where the asset lives in your media library
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.PublicID, resp.SecureURL)
}
```

### Upload
### Build and optimize a delivery URL

- [See full documentation](https://cloudinary.com/documentation/go_image_and_video_upload).
- [Learn more about configuring your uploads with upload presets](https://cloudinary.com/documentation/upload_presets).
`cld.Image(publicID)` returns an `*asset.Asset` whose `String()` method serializes a delivery URL — no network call. Set the `Transformation` field with raw transformation syntax. This one scales to 500px wide and lets Cloudinary pick the format and quality for the requesting browser (`f_auto`, `q_auto`):

```go
resp, err := cld.Upload.Upload(ctx, "my_picture.jpg", uploader.UploadParams{})
```

### Security options
package main

- [See full documentation](https://cloudinary.com/documentation/solution_overview#security).

### Logging
import (
"fmt"
"log"

Cloudinary SDK logs errors using standard `go log` functions.
"github.com/cloudinary/cloudinary-go/v2"
)

For details on redefining the logger or adjusting the logging level, see [Logging](logger/README.md).
func main() {
cld, err := cloudinary.NewFromParams("demo", "my_key", "my_secret")
if err != nil {
log.Fatal(err)
}

image, err := cld.Image("sample")
if err != nil {
log.Fatal(err)
}
image.Transformation = "c_scale,w_500/f_auto/q_auto"

url, err := image.String()
if err != nil {
log.Fatal(err)
}
fmt.Println(url)
// https://res.cloudinary.com/demo/image/upload/c_scale,w_500/f_auto/q_auto/sample
}
```

### Complete SDK Example
### Retrieve asset details with the Admin API

See [Complete SDK Example](example/example.go).
`cld.Admin.Assets(ctx, admin.AssetsParams{...})` returns an `*admin.AssetsResult`. Its `Assets` field is a slice of assets, each with `PublicID` and `SecureURL`:

## Contributions
```go
package main

- Ensure tests run locally
- Open a PR and ensure Travis tests pass
- For more information on how to contribute, take a look at the [contributing](CONTRIBUTING.md) page.
import (
"context"
"fmt"
"log"

## Get Help
"github.com/cloudinary/cloudinary-go/v2"
"github.com/cloudinary/cloudinary-go/v2/api/admin"
)

If you run into an issue or have a question, you can either:
func main() {
cld, err := cloudinary.New() // reads CLOUDINARY_URL from the environment
if err != nil {
log.Fatal(err)
}

res, err := cld.Admin.Assets(context.Background(), admin.AssetsParams{
Prefix: "cms/",
MaxResults: 30,
})
if err != nil {
log.Fatal(err)
}
for _, a := range res.Assets {
fmt.Println(a.PublicID, a.SecureURL)
}
}
```

- Issues related to the SDK: [Open a GitHub issue](https://github.com/cloudinary/cloudinary-go/issues).
- Issues related to your account: [Open a support ticket](https://cloudinary.com/contact)
## For AI agents

## About Cloudinary
`cloudinary-go` is the Go server-side SDK — upload, transformation and delivery URLs, and the Admin API, where the API secret stays private. Construct a client with `cloudinary.New()` (reads `CLOUDINARY_URL`), `cloudinary.NewFromURL`, or `cloudinary.NewFromParams`. Upload lives under `api/uploader`, admin under `api/admin`. For tasks this package doesn't cover, use a sibling package:

Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently
manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive
and personalized visual-media experiences—irrespective of the viewing device.
| Task | Package |
|---|---|
| Only the AI Content Analysis API, as a typed client | [`analysis-go`](https://github.com/cloudinary/analysis-go) |
| Provisioning — product environments, users, access keys | [`account-provisioning-go`](https://github.com/cloudinary/account-provisioning-go) |
| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) |

## Additional Resources
Go has no first-party browser runtime, so there is no Go equivalent of the JavaScript `url-gen` split — URL building and credential handling both live in this SDK.

- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references):
Comprehensive references, including syntax and examples for all SDKs.
- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers
- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on
YouTube.
- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and
on-site courses.
- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop
for all code explorers, Postman collections, and feature demos found in the docs.
- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should
develop next.
- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to
other Cloudinary developers.
- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration.
- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and
more.
## Links

## Licence
- [Go SDK guide](https://cloudinary.com/documentation/go_integration)
- [Upload](https://cloudinary.com/documentation/go_image_and_video_upload)
- [Asset administration (Admin API)](https://cloudinary.com/documentation/go_asset_administration)
- [Media transformations](https://cloudinary.com/documentation/go_media_transformations)
- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references)
- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt)
- [Package on pkg.go.dev](https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2)

Released under the MIT license.