Go SDK for the Anytype local API. Compatible with API version 2025-11-08.
go get github.com/epheo/anytype-goimport (
"github.com/epheo/anytype-go"
_ "github.com/epheo/anytype-go/client"
)client := anytype.NewClient(
anytype.WithBaseURL("http://localhost:31009"),
)
// Initiate challenge — Anytype app will display a verification code
auth, _ := client.Auth().CreateChallenge(ctx, "MyApp")
// User enters the code
var code string
fmt.Scanln(&code)
// Exchange for API key
token, _ := client.Auth().CreateApiKey(ctx, auth.ChallengeID, code)
// Create authenticated client
client = anytype.NewClient(
anytype.WithBaseURL("http://localhost:31009"),
anytype.WithAppKey(token.ApiKey),
)The SDK uses a fluent interface that mirrors the resource hierarchy:
// Spaces
spaces, _ := client.Spaces().List(ctx)
space, _ := client.Space(spaceID).Get(ctx)
work, _ := client.Spaces().GetByName(ctx, "Work") // exact match, ErrSpaceNotFound otherwise
// Objects
objects, _ := client.Space(spaceID).Objects().List(ctx) // objects.Data, objects.Pagination
object, _ := client.Space(spaceID).Object(objectID).Get(ctx)
markdown, _ := client.Space(spaceID).Object(objectID).Get(ctx, anytype.WithFormat("md"))
// Types and templates
types, _ := client.Space(spaceID).Types().List(ctx)
task, _ := client.Space(spaceID).Types().Get(ctx, "task") // by key; Type(id) takes an ID
templates, _ := client.Space(spaceID).Type(task.ID).Templates().List(ctx)
// Lists and views
views, _ := client.Space(spaceID).List(listID).Views().List(ctx)
_ = client.Space(spaceID).List(listID).Objects().Add(ctx, []string{objectID})
// Properties and tags
props, _ := client.Space(spaceID).Properties().List(ctx)
tags, _ := client.Space(spaceID).Property(propID).Tags().List(ctx)
// Members
members, _ := client.Space(spaceID).Members().List(ctx)
// Search (within a space or globally)
results, _ := client.Space(spaceID).Search(ctx, anytype.SearchRequest{
Query: "meeting notes",
Types: []string{"page"},
Sort: &anytype.SortOptions{
Property: anytype.SortPropertyLastModifiedDate,
Direction: anytype.SortDirectionDesc,
},
})
globalResults, _ := client.Search().Search(ctx, anytype.SearchRequest{Query: "notes"})Every List and Search returns a *Page[T] holding one page of Data plus a
Pagination cursor, and accepts WithLimit/WithOffset:
page, _ := client.Space(spaceID).Objects().List(ctx, anytype.WithLimit(50), anytype.WithOffset(100))
for _, obj := range page.Data { /* ... */ }
if page.Pagination.HasMore { /* fetch the next page */ }To walk every page without managing offsets yourself, use All, which returns a
Go 1.23 iterator (iter.Seq2[T, error]):
for obj, err := range client.Space(spaceID).Objects().All(ctx) {
if err != nil {
return err
}
// ... use obj
}All is available on every list, and on Search (client.Search().All(ctx, req),
client.Space(spaceID).SearchAll(ctx, req)).
Non-2xx responses come back as *anytype.APIError carrying the server's
Status, Code and Message. Any 404, and the by-key/by-name lookups that
scan a list, match anytype.ErrNotFound:
_, err := client.Space(spaceID).Types().Get(ctx, "nope")
if errors.Is(err, anytype.ErrNotFound) { /* no such type */ }
var apiErr *anytype.APIError
if errors.As(err, &apiErr) && apiErr.Status == 429 { /* back off */ }Property formats, tag colors and creatable type layouts are typed constants
(anytype.PropertyFormatText, anytype.ColorRed, anytype.TypeLayoutNote).
When the format is only known at runtime, NewPropertyLinkValue picks the
right typed value and rejects a mismatched Go type before the request is sent:
v, err := anytype.NewPropertyLinkValue(prop.Key, prop.Format, 42)
obj, _ := client.Space(spaceID).Objects().Create(ctx, anytype.CreateObjectRequest{
TypeKey: "task",
Name: "Pay invoice",
Icon: anytype.EmojiIcon("💸"),
Properties: []anytype.PropertyLinkValue{v},
})See examples/usage_examples.go for complete working examples and GoDoc for the full API reference.
go test -v ./tests_api_coverage/... # API coverage testsApache License 2.0 - see LICENSE.