codeatlas

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 13 Imported by: 0

README

codeatlas-sdk-go

Go Reference

Official Go client for the public CodeAtlas API. Standard library only, no dependencies. Homepage: https://codeatlas.com.br · API docs: https://codeatlas.com.br/docs · OpenAPI: https://codeatlas.com.br/openapi.json

Sibling SDKs: JavaScript · Python

Install

go get github.com/codeatlasdev/codeatlas-sdk-go

Requires Go 1.23 or newer.

Read the catalog (no authentication)

package main

import (
	"context"
	"fmt"
	"log"

	codeatlas "github.com/codeatlasdev/codeatlas-sdk-go"
)

func main() {
	ctx := context.Background()
	client := codeatlas.New() // base URL defaults to https://codeatlas.com.br/api/v1

	page, err := client.Services.List(ctx, &codeatlas.ListParams{Limit: 20})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(page.Count, page.Data[0].Name, page.NextCursor)

	// Iterate every service, following next_cursor.
	for svc, err := range client.Services.All(ctx, nil) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(svc.Slug)
	}

	svc, err := client.Services.Get(ctx, "zelvo-ai")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(svc.Name, svc.DeliveryTimeline)

	// Up to 50 slugs in one call. Unknown slugs are 404 items, not errors.
	results, _ := client.Services.Batch(ctx, []string{"zelvo-ai", "nope"})
	fmt.Println(results[0].Status, results[1].Status) // 200 404

	// Client-side filter: the API has no search endpoint.
	hits, _ := client.Services.Search(ctx, "whatsapp")
	fmt.Println(len(hits))

	health, _ := client.Health(ctx)
	fmt.Println(health.Status) // ok
}

Errors

Every non-2xx response is an *codeatlas.APIError carrying the API's error.code, error.message and error.hint. OAuth errors (invalid_client, ...) use the same type.

_, err := client.Services.Get(ctx, "nope")

var apiErr *codeatlas.APIError
if errors.As(err, &apiErr) {
	fmt.Println(apiErr.Status, apiErr.Code, apiErr.Message, apiErr.Hint)
	// 404 not_found ... ...
}

codeatlas.IsNotFound(err)    // true
codeatlas.IsRateLimited(err) // 429; apiErr.RetryAfter has the Retry-After wait

Rate limits

Every response under /api/v1 carries RateLimit and RateLimit-Policy (IETF draft); the legacy X-RateLimit-* headers are used as a fallback. The client keeps the latest values, and a failed call carries them on the error:

rl := client.LastRateLimit()
fmt.Println(rl.Policy, rl.Remaining, "of", rl.Limit, "per", rl.Window, "- resets in", rl.Reset)
// read 119 of 120 per 1m0s - resets in 36s

Write calls (OAuth 2.0 client credentials)

Contact requests and exports need a Bearer token. Register a client once (RFC 7591), store the secret (it is shown once) and pass it to New. The client fetches the token and caches it until shortly before it expires.

creds, err := codeatlas.Register(ctx, "my-agent")
if err != nil {
	log.Fatal(err)
}
client := codeatlas.New(codeatlas.WithCredentials(creds.ClientID, creds.ClientSecret))

receipt, err := client.ContactRequests.Create(ctx, codeatlas.ContactRequestInput{
	Name:        "Ana Souza",
	Email:       "ana@example.com",
	Message:     "Quero um diagnóstico do meu atendimento.",
	ServiceSlug: "zelvo-ai",
}, codeatlas.WithIdempotencyKey("a-unique-key-per-intent")) // 8 to 128 printable ASCII; makes retries safe
fmt.Println(receipt.ID, receipt.Status) // cr_..., received

Only send a contact request after the person asked you to and gave you their name and email. Limit: 5 per hour per OAuth client.

Exports
job, err := client.Exports.Create(ctx, codeatlas.ExportCSV) // ExportJSONL | ExportCSV | ExportMD; 10 per hour per client
if err != nil {
	log.Fatal(err)
}
if _, err := client.Exports.Wait(ctx, job.ID, nil); err != nil { // polls every 1s, gives up after 60s
	log.Fatal(err)
}
file, err := client.Exports.Download(ctx, job.ID) // []byte

Sandbox

The sandbox serves the same paths and OAuth flow with fixture data: writes are validated, nothing is stored or sent.

client := codeatlas.New(
	codeatlas.WithBaseURL(codeatlas.SandboxBaseURL),
	codeatlas.WithCredentials(creds.ClientID, creds.ClientSecret),
)

The token is requested with resource set to the client's base URL, so the same credentials work for both environments.

Options

Option Purpose
WithBaseURL(url) API root, e.g. codeatlas.SandboxBaseURL
WithCredentials(id, secret) OAuth client credentials for write calls
WithHTTPClient(*http.Client) Custom timeout, proxy or transport (default timeout 15s)
WithOrigin(url) Origin of /oauth2/* (tests only)

Development

go vet ./...
go test ./...          # includes live read tests against https://codeatlas.com.br
go test -short ./...   # offline: skips the live tests

Releases: push a tag vX.Y.Z. A public repo with go.mod and a semver tag is a published Go module.

MIT licensed.

Documentation

Overview

Package codeatlas is a Go client for the public CodeAtlas API.

CodeAtlas is a Brazilian software studio; its official homepage is https://codeatlas.com.br. This is the official Go SDK, published by the codeatlasdev GitHub organization. API documentation lives at https://codeatlas.com.br/docs and the OpenAPI description at https://codeatlas.com.br/openapi.json. Sibling SDKs exist for JavaScript (https://github.com/codeatlasdev/codeatlas-sdk-js) and Python (https://github.com/codeatlasdev/codeatlas-sdk-python).

Read endpoints (services, health, batch) need no authentication:

client := codeatlas.New()
page, err := client.Services.List(ctx, &codeatlas.ListParams{Limit: 20})

Write endpoints (contact requests, exports) use OAuth 2.0 client credentials. Register once, keep the secret, and pass it to New:

creds, err := codeatlas.Register(ctx, "my-agent")
client := codeatlas.New(codeatlas.WithCredentials(creds.ClientID, creds.ClientSecret))

The client fetches and caches the access token for you. Use WithBaseURL with SandboxBaseURL to try write calls without anything being stored or sent. Every non-2xx response is returned as an *APIError.

Index

Constants

View Source
const (
	// DefaultBaseURL is the production API.
	DefaultBaseURL = "https://codeatlas.com.br/api/v1"
	// SandboxBaseURL is the same API with no side effects: writes are
	// validated but nothing is stored or sent.
	SandboxBaseURL = "https://codeatlas.com.br/api/sandbox/v1"
	// Origin is the CodeAtlas origin that hosts the OAuth endpoints.
	Origin = "https://codeatlas.com.br"

	// Version is the SDK version, sent in the User-Agent header.
	Version = "0.1.0"
)
View Source
const (
	CodeBadRequest       = "bad_request"
	CodeConflict         = "conflict"
	CodeForbidden        = "forbidden"
	CodeInvalidClient    = "invalid_client"
	CodeInvalidToken     = "invalid_token"
	CodeMethodNotAllowed = "method_not_allowed"
	CodeNotFound         = "not_found"
	CodePayloadTooLarge  = "payload_too_large"
	CodeRateLimited      = "rate_limited"
	CodeUnauthorized     = "unauthorized"
	CodeUnprocessable    = "unprocessable"
	CodeUnsupportedMedia = "unsupported_media_type"
)

Error codes of the API error envelope (plus the OAuth codes the token and registration endpoints return, such as "invalid_client").

View Source
const (
	ExportQueued    = "queued"
	ExportRunning   = "running"
	ExportSucceeded = "succeeded"
)

Export statuses.

Variables

This section is empty.

Functions

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is an API error with code not_found.

func IsRateLimited

func IsRateLimited(err error) bool

IsRateLimited reports whether err is an API error with status 429.

Types

type APIError

type APIError struct {
	// Status is the HTTP status code.
	Status int
	// Code is the stable machine-readable error code, e.g. "not_found".
	Code string
	// Message is the human-readable description.
	Message string
	// Hint says how to fix the request. Empty for OAuth errors.
	Hint string
	// RetryAfter is the Retry-After wait on a 429, zero otherwise.
	RetryAfter time.Duration
	// RateLimit is the rate-limit state sent with the failed response.
	RateLimit RateLimit
}

APIError is returned for every non-2xx response. It mirrors the API error envelope {"error": {"code", "message", "hint"}} and also understands OAuth errors (RFC 6749 / 7591).

func (*APIError) Error

func (e *APIError) Error() string

type BatchError

type BatchError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Hint    string `json:"hint"`
}

BatchError is the per-item error of a BatchResult.

type BatchResult

type BatchResult struct {
	// Slug is nil when the requested item was not a string.
	Slug *string `json:"slug"`
	// Status is the HTTP-style status of this item: 200, 404 or 400.
	Status int         `json:"status"`
	Data   *Service    `json:"data,omitempty"`
	Error  *BatchError `json:"error,omitempty"`
}

BatchResult is the outcome of one slug in ServicesService.Batch.

type Client

type Client struct {
	// Services is the public service catalog.
	Services *ServicesService
	// ContactRequests sends first-conversation requests. Needs credentials.
	ContactRequests *ContactRequestsService
	// Exports runs asynchronous catalog exports. Needs credentials.
	Exports *ExportsService
	// contains filtered or unexported fields
}

Client talks to the CodeAtlas API. Create it with New; it is safe for concurrent use.

func New

func New(opts ...Option) *Client

New returns a client for the production API. Pass options to change that.

func (*Client) BaseURL

func (c *Client) BaseURL() string

BaseURL returns the API root the client talks to.

func (*Client) Health

func (c *Client) Health(ctx context.Context) (*Health, error)

Health checks API liveness.

func (*Client) LastRateLimit

func (c *Client) LastRateLimit() RateLimit

LastRateLimit returns the rate-limit state parsed from the most recent response that carried RateLimit headers. The zero value means none seen yet.

type ContactRequest

type ContactRequest struct {
	ID     string `json:"id"`
	Status string `json:"status"`
	// Delivery is "delivered" or "stored" in production, "sandbox" in the sandbox.
	Delivery  string    `json:"delivery"`
	CreatedAt time.Time `json:"created_at"`
}

ContactRequest is the receipt of a contact request.

type ContactRequestInput

type ContactRequestInput struct {
	// Name is the person's full name, 2 to 120 characters.
	Name string `json:"name"`
	// Email is where CodeAtlas replies.
	Email string `json:"email"`
	// Message is what the person wants to discuss, 10 to 2000 characters.
	Message string `json:"message"`
	// Company is optional, up to 160 characters.
	Company string `json:"company,omitempty"`
	// Locale defaults to pt-BR on the server.
	Locale Locale `json:"locale,omitempty"`
	// ServiceSlug is one of the slugs returned by the catalog.
	ServiceSlug string `json:"service_slug,omitempty"`
}

ContactRequestInput is the body of ContactRequestsService.Create.

type ContactRequestsService

type ContactRequestsService struct {
	// contains filtered or unexported fields
}

ContactRequestsService sends first-conversation requests to the CodeAtlas team. Needs OAuth credentials (WithCredentials).

func (*ContactRequestsService) Create

Create sends a contact request to the CodeAtlas team (5 per hour per OAuth client). Only call it after the person asked you to and gave you their name and email. In the sandbox the request is accepted and never delivered.

type CreateOption

type CreateOption func(*createConfig)

CreateOption customizes a write call.

func WithIdempotencyKey

func WithIdempotencyKey(key string) CreateOption

WithIdempotencyKey sets the Idempotency-Key header (8 to 128 printable ASCII characters) so retries are safe: a replay returns the original result.

type Credentials

type Credentials struct {
	ClientID     string
	ClientSecret string
}

Credentials are OAuth 2.0 client credentials.

type ExportFormat

type ExportFormat string

ExportFormat is the file format of an export.

const (
	ExportJSONL ExportFormat = "jsonl"
	ExportCSV   ExportFormat = "csv"
	ExportMD    ExportFormat = "md"
)

Supported export formats.

type ExportJob

type ExportJob struct {
	ID string `json:"id"`
	// Status is "queued", "running" or "succeeded".
	Status string       `json:"status"`
	Format ExportFormat `json:"format"`
	// DownloadURL is set when Status is "succeeded".
	DownloadURL *string   `json:"download_url"`
	CreatedAt   time.Time `json:"created_at"`
	// ExpiresAt is when the job and its file are dropped (24 hours).
	ExpiresAt time.Time `json:"expires_at"`
}

ExportJob is an asynchronous catalog export.

type ExportsService

type ExportsService struct {
	// contains filtered or unexported fields
}

ExportsService runs asynchronous catalog exports. Needs OAuth credentials (WithCredentials). Jobs are visible only to the client that created them.

func (*ExportsService) Create

func (s *ExportsService) Create(ctx context.Context, format ExportFormat, opts ...CreateOption) (*ExportJob, error)

Create starts an export job (10 per hour per OAuth client).

func (*ExportsService) Download

func (s *ExportsService) Download(ctx context.Context, id string) ([]byte, error)

Download returns the file of a succeeded job.

func (*ExportsService) Get

func (s *ExportsService) Get(ctx context.Context, id string) (*ExportJob, error)

Get returns the current state of an export job.

func (*ExportsService) Wait

func (s *ExportsService) Wait(ctx context.Context, id string, opts *WaitOptions) (*ExportJob, error)

Wait polls until the job has succeeded. It fails when the timeout elapses or ctx is done.

type Health

type Health struct {
	Status  string `json:"status"`
	Service string `json:"service"`
	Version string `json:"version"`
}

Health is the API liveness response.

type ListParams

type ListParams struct {
	// Limit is the page size, 1 to 100 (server default 20).
	Limit int
	// Cursor is the NextCursor of the previous page.
	Cursor string
}

ListParams are the query parameters of ServicesService.List. Zero values are omitted.

type Locale

type Locale string

Locale is the reply language of a contact request.

const (
	LocalePTBR Locale = "pt-BR"
	LocaleEN   Locale = "en"
)

Supported locales.

type Option

type Option func(*Client)

Option configures a Client.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL points the client at another API root, e.g. SandboxBaseURL.

func WithCredentials

func WithCredentials(clientID, clientSecret string) Option

WithCredentials sets the OAuth client credentials used by write calls. Get them with Register.

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient replaces the underlying *http.Client (timeouts, proxies, transports). The default has a 15 second timeout.

func WithOrigin

func WithOrigin(origin string) Option

WithOrigin overrides the origin that serves /oauth2/register and /oauth2/token. Only useful in tests; defaults to Origin.

type RateLimit

type RateLimit struct {
	// Policy is the name of the policy that applies, e.g. "read".
	Policy string
	// Limit is the quota per window (RateLimit-Policy q, or X-RateLimit-Limit).
	Limit int
	// Window is the window length (RateLimit-Policy w); zero if unknown.
	Window time.Duration
	// Remaining is the requests left in the window.
	Remaining int
	// Reset is the time until the window resets.
	Reset time.Duration
}

RateLimit is the quota state from the IETF draft-ietf-httpapi-ratelimit-headers headers (RateLimit and RateLimit-Policy), falling back to the legacy X-RateLimit-* headers. The zero value means the response had none.

type RegisteredClient

type RegisteredClient struct {
	Credentials
	ClientName string
}

RegisteredClient is the result of Register.

func Register

func Register(ctx context.Context, clientName string, opts ...Option) (*RegisteredClient, error)

Register registers a new OAuth client (RFC 7591) and returns its credentials. The secret is shown once: store it. It uses the production origin unless WithOrigin is passed.

type Service

type Service struct {
	Slug             string   `json:"slug"`
	Name             string   `json:"name"`
	Description      string   `json:"description"`
	ServiceType      string   `json:"serviceType"`
	URL              string   `json:"url"`
	Capabilities     []string `json:"capabilities"`
	DeliveryTimeline string   `json:"deliveryTimeline"`
}

Service is one entry of the CodeAtlas service catalog.

type ServiceList

type ServiceList struct {
	Data []Service `json:"data"`
	// Count is the total number of services, not the page size.
	Count int `json:"count"`
	// NextCursor is the cursor of the next page; nil on the last page.
	NextCursor *string `json:"next_cursor"`
}

ServiceList is one page of the catalog.

type ServicesService

type ServicesService struct {
	// contains filtered or unexported fields
}

ServicesService is the public service catalog. No authentication needed.

func (*ServicesService) All

All iterates over every service, following next_cursor. params.Cursor is ignored; params may be nil. The iteration stops after the first error, which is yielded as the last pair:

for svc, err := range client.Services.All(ctx, nil) {
	if err != nil { return err }
	fmt.Println(svc.Slug)
}

func (*ServicesService) Batch

func (s *ServicesService) Batch(ctx context.Context, slugs []string) ([]BatchResult, error)

Batch looks up up to 50 slugs in one call. Unknown slugs come back as items with Status 404, not as an error.

func (*ServicesService) Get

func (s *ServicesService) Get(ctx context.Context, slug string) (*Service, error)

Get returns one service by slug. A missing slug yields an *APIError with code "not_found" (see IsNotFound).

func (*ServicesService) List

func (s *ServicesService) List(ctx context.Context, params *ListParams) (*ServiceList, error)

List returns one page of the catalog. params may be nil.

func (*ServicesService) Search

func (s *ServicesService) Search(ctx context.Context, query string) ([]Service, error)

Search filters the full catalog on the client: a case-insensitive match of every whitespace-separated term against slug, name, description, type and capabilities. The API has no search endpoint.

type WaitOptions

type WaitOptions struct {
	// Interval between polls. Default 1 second.
	Interval time.Duration
	// Timeout for the whole wait. Default 60 seconds.
	Timeout time.Duration
}

WaitOptions tune ExportsService.Wait. Zero values mean the defaults.

Jump to

Keyboard shortcuts

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