Documentation
¶
Overview ¶
Package polyzon is the official Go client for the Polyzon public API (https://api.polyzon.org): search across 3D-model catalogues and fetch model cards, with the account's quota and token information.
Create one Client and share it: it is safe for concurrent use by many goroutines and keeps a pool of keep-alive connections.
client, err := polyzon.NewClient() // reads POLYZON_API_KEY
if err != nil {
log.Fatal(err)
}
page, err := client.Search(ctx, polyzon.SearchParams{Query: "дракон"})
Every method takes a context.Context first; cancelling it aborts the request and any retry wait. Errors returned by the API are *APIError values that match the sentinel errors of this package through errors.Is, for example errors.Is(err, polyzon.ErrRateLimited).
Keep the token on the server side: never ship it to browsers or mobile apps.
Index ¶
- Constants
- Variables
- type APIError
- type Account
- type Client
- func (c *Client) CloseIdleConnections()
- func (c Client) Format(f fmt.State, _ rune)
- func (c *Client) GetModel(ctx context.Context, source, id string, opts ...ModelOption) (*Model, error)
- func (c *Client) GetModels(ctx context.Context, refs []ModelRef, opts ...ModelOption) ([]ModelResult, error)
- func (c *Client) Limits(ctx context.Context) (*Limits, error)
- func (c *Client) Me(ctx context.Context) (*Me, error)
- func (c *Client) Search(ctx context.Context, params SearchParams) (*SearchPage, error)
- func (c *Client) SearchAll(ctx context.Context, params SearchParams) iter.Seq2[SearchItem, error]
- func (c Client) String() string
- type ItemStats
- type License
- type Limits
- type Me
- type Meta
- type Model
- type ModelOption
- type ModelRef
- type ModelResult
- type ModelStats
- type Option
- func WithAPIKey(key string) Option
- func WithBaseURL(baseURL string) Option
- func WithHTTPClient(httpClient *http.Client) Option
- func WithLogger(logger *slog.Logger) Option
- func WithMaxConnections(n int) Option
- func WithMaxRetries(retries int) Option
- func WithProxy(proxyURL *url.URL) Option
- func WithTimeout(timeout time.Duration) Option
- func WithUserAgent(suffix string) Option
- type Price
- type QuotaWindow
- type RateLimit
- type SearchItem
- type SearchPage
- type SearchParams
- type TokenInfo
Examples ¶
Constants ¶
const ( SourceThingiverse = "thingiverse" SourceCults3D = "cults3d" SourcePrintables = "printables" SourceMakerWorld = "makerworld" Source3DToday = "3dtoday" SourceCrealityCloud = "crealitycloud" SourceMyMiniFactory = "myminifactory" SourceThangs = "thangs" SourceYouMagine = "youmagine" SourceGrabCAD = "grabcad" SourceSketchfab = "sketchfab" SourceThreeding = "threeding" SourceNexprint = "nexprint" SourceNASA = "nasa" SourceNIH3D = "nih3d" SourceSmithsonian = "smithsonian" SourcePinshape = "pinshape" SourceCGTrader = "cgtrader" SourceGambody = "gambody" SourceJewelModel = "jewelmodel" SourceMakerOnline = "makeronline" Source3DExport = "3dexport" )
Known sources (catalogues) of models. The API may add new sources at any time, so every field and parameter holding a source is a plain string.
const ( LicenseCC0 = "cc0" LicenseCCBY = "cc-by" LicenseCCBYSA = "cc-by-sa" LicenseCCBYND = "cc-by-nd" LicenseCCBYNC = "cc-by-nc" LicenseCCBYNCSA = "cc-by-nc-sa" LicenseCCBYNCND = "cc-by-nc-nd" LicenseGPL = "gpl" LicenseLGPL = "lgpl" LicenseMIT = "mit" LicenseBSD = "bsd" LicensePrivateUse = "private-use" LicenseCommercial = "commercial" LicenseCustom = "custom" LicenseUnknown = "unknown" )
Known license ids, used by SearchParams.Licenses, SearchItem.License and License.ID. New ids may appear, so the fields are plain strings.
const ( SortRelevant = "relevant" // by relevance (the default) SortPopular = "popular" // by popularity on the source SortNewest = "newest" SortLikes = "likes" SortMakes = "makes" SortDownloads = "downloads" )
Sort orders for SearchParams.Sort.
const ( LangRU = "ru" // the default LangEN = "en" )
Languages for titles, descriptions and tags (SearchParams.Lang, WithLang). Texts originally in another language are machine-translated.
const ( PriceFree = "free" PricePaid = "paid" PriceOpen = "open" )
Values of Price.Type.
const ( TotalEq = "eq" // Total is exact TotalGte = "gte" // Total is a lower bound )
Values of SearchPage.TotalRelation.
const ( CodeBadRequest = "bad_request" // 400, see APIError.Param CodePageTooDeep = "page_too_deep" // 400, page × size > 2400 CodeInvalidToken = "invalid_token" // 401, unknown or revoked token CodeAccountActionRequired = "account_action_required" // 403, accept the terms at polyzon.org/account CodeNotFound = "not_found" // 404 CodeGone = "gone" // 410, removed on the right holder's request CodeRateLimited = "rate_limited" // 429, per-minute limit CodeQuotaExceeded = "quota_exceeded" // 429, daily quota, resets at 00:00 UTC CodeInternal = "internal" // 500 )
Error codes of APIError.Code.
const DefaultBaseURL = "https://api.polyzon.org"
DefaultBaseURL is the production API endpoint.
const Version = "1.0.0"
Version is the version of this SDK. It is sent in the User-Agent header.
Variables ¶
var ( // ErrBadRequest matches HTTP 400: a parameter is invalid (APIError.Param names // it) or the page is too deep (code page_too_deep). ErrBadRequest error = &sentinel{msg: "polyzon: bad request"} // ErrAuthentication matches HTTP 401: the token is missing, unknown or revoked. ErrAuthentication error = &sentinel{msg: "polyzon: authentication failed"} // ErrPermissionDenied matches HTTP 403: the token owner must accept the current // terms at https://polyzon.org/account/. ErrPermissionDenied error = &sentinel{msg: "polyzon: permission denied"} // ErrNotFound matches HTTP 404. ErrNotFound error = &sentinel{msg: "polyzon: not found"} // ErrGone matches HTTP 410: the model was removed on the right holder's // request. Delete your copy of it too. ErrGone error = &sentinel{msg: "polyzon: gone"} // ErrRateLimited matches every HTTP 429, including [ErrQuotaExceeded]. ErrRateLimited error = &sentinel{msg: "polyzon: rate limited"} // ErrQuotaExceeded matches HTTP 429 with code quota_exceeded: the daily quota // is spent until 00:00 UTC. It also matches [ErrRateLimited]. ErrQuotaExceeded error = &sentinel{msg: "polyzon: daily quota exceeded", parent: ErrRateLimited} // ErrServer matches HTTP 5xx answers. ErrServer error = &sentinel{msg: "polyzon: server error"} // ErrConnection matches network failures: DNS, TCP, TLS, proxy, reset // connections, and timeouts ([ErrTimeout]). ErrConnection error = &sentinel{msg: "polyzon: connection error"} // ErrTimeout matches a request attempt that ran out of time (see [WithTimeout]). // It also matches [ErrConnection]. ErrTimeout error = &sentinel{msg: "polyzon: request timed out", parent: ErrConnection} // ErrInvalidResponse matches a success answer whose body is not a JSON // object or exceeds 8 MiB. ErrInvalidResponse error = &sentinel{msg: "polyzon: invalid response"} )
Sentinel errors for errors.Is. Errors answered by the API are *APIError values matching one of the HTTP-status sentinels; transport problems match ErrConnection (and ErrTimeout when time ran out); malformed success answers match ErrInvalidResponse.
Errors caused by the caller's context (cancellation or its deadline) are not wrapped in any of these: they match context.Canceled or context.DeadlineExceeded instead.
Functions ¶
This section is empty.
Types ¶
type APIError ¶
type APIError struct {
// StatusCode is the HTTP status code.
StatusCode int
// Code is the stable machine-readable error code (the Code* constants), or ""
// when the body was not a problem document.
Code string
// Title is the short HTTP status title.
Title string
// Detail is the human-readable explanation (usually in Russian).
Detail string
// Param names the invalid query parameter for code bad_request, or "".
Param string
// RequestID is the X-Request-ID response header; quote it in support requests.
RequestID string
// RetryAfter is the Retry-After header as a duration, or 0 when absent.
RetryAfter time.Duration
// Header holds the response headers (for example x-ratelimit-*).
Header http.Header
}
APIError is an error answer of the API (any non-2xx HTTP status, including a redirect, which the client never follows). The API answers application/problem+json; for other bodies (an HTML page from an edge proxy) Code is empty and Detail is "HTTP <status>".
Use errors.Is with the sentinel errors to classify it and errors.As to read its fields:
var apiErr *polyzon.APIError
if errors.As(err, &apiErr) && apiErr.Code == polyzon.CodePageTooDeep { … }
Example ¶
package main
import (
"context"
"errors"
"fmt"
"log"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
client, err := polyzon.NewClient()
if err != nil {
log.Fatal(err)
}
_, err = client.GetModel(context.Background(), polyzon.SourceThingiverse, "tv-404")
switch {
case errors.Is(err, polyzon.ErrNotFound):
fmt.Println("no such model")
case errors.Is(err, polyzon.ErrGone):
fmt.Println("removed on the right holder's request: delete it")
case errors.Is(err, polyzon.ErrQuotaExceeded):
fmt.Println("daily quota spent until 00:00 UTC")
case errors.Is(err, polyzon.ErrConnection):
fmt.Println("network trouble:", err)
}
var apiErr *polyzon.APIError
if errors.As(err, &apiErr) {
fmt.Println(apiErr.StatusCode, apiErr.Code, apiErr.RequestID)
}
}
Output: no such model 404 not_found example
type Account ¶
type Account struct {
ID string `json:"id"`
DisplayName string `json:"displayName"` // "" when not set
CreatedAt string `json:"createdAt"` // ISO-8601
}
Account is the Polyzon account owning the token.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client calls the Polyzon API. Create it with NewClient. A Client is immutable and safe for concurrent use by multiple goroutines; share one per process so requests reuse its pool of keep-alive connections.
func NewClient ¶
NewClient creates a client. Without WithAPIKey the token is read from the POLYZON_API_KEY environment variable; a missing or malformed token is an error.
Example ¶
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
// The token comes from POLYZON_API_KEY; polyzon.WithAPIKey passes it explicitly.
client, err := polyzon.NewClient(
polyzon.WithTimeout(10*time.Second),
polyzon.WithMaxRetries(3),
polyzon.WithUserAgent("my-bot/1.0"),
)
if err != nil {
log.Fatal(err)
}
me, err := client.Me(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Println(me.Account.DisplayName, me.Token.Prefix)
}
Output: Алексей pzk_Q7xR2mVb
func (*Client) CloseIdleConnections ¶
func (c *Client) CloseIdleConnections()
CloseIdleConnections closes the idle keep-alive connections of the client's pool (of the custom client's transport with WithHTTPClient). The client stays usable.
func (Client) Format ¶
Format implements fmt.Formatter so that every verb, including %+v and %#v, prints Client.String and never the token.
func (*Client) GetModel ¶
func (c *Client) GetModel(ctx context.Context, source, id string, opts ...ModelOption) (*Model, error)
GetModel returns the model card of the model id on source, the same pair as in search results and in polyzon.org/model/{source}/{id}. It costs one request of the daily quota. An invalid source or id is reported without a request.
A removed model answers ErrGone: delete your copy of it too.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
client, err := polyzon.NewClient()
if err != nil {
log.Fatal(err)
}
model, err := client.GetModel(context.Background(), polyzon.SourceThingiverse, "tv-1234567",
polyzon.WithLang(polyzon.LangRU))
if err != nil {
log.Fatal(err)
}
fmt.Println(model.Title)
fmt.Println("license:", model.License.ID)
if model.Stats.Downloads != nil {
fmt.Println("downloads:", *model.Stats.Downloads)
}
for _, other := range model.Copies {
fmt.Println("also on", other.Source, other.ID)
}
}
Output: Дракон с подвижными сочленениями (пример) license: cc-by-nc downloads: 410000 also on printables pr-123456
func (*Client) GetModels ¶
func (c *Client) GetModels(ctx context.Context, refs []ModelRef, opts ...ModelOption) ([]ModelResult, error)
GetModels fetches many model cards with bounded parallelism (WithConcurrency, default 4) and returns one result per ref in input order. Failures are reported per result, never as the returned error, which is only for invalid options.
Once a request fails with ErrAuthentication, ErrPermissionDenied or ErrQuotaExceeded, the refs not started yet get that same error without requests. Each fetched model costs one request of the daily quota.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"log"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
client, err := polyzon.NewClient()
if err != nil {
log.Fatal(err)
}
refs := []polyzon.ModelRef{
{Source: polyzon.SourceThingiverse, ID: "tv-1234567"},
{Source: polyzon.SourceThingiverse, ID: "tv-404"},
}
results, err := client.GetModels(context.Background(), refs, polyzon.WithConcurrency(4))
if err != nil {
log.Fatal(err)
}
for _, res := range results { // in the order of refs
if res.Err != nil {
fmt.Println(res.Ref.ID, "not found:", errors.Is(res.Err, polyzon.ErrNotFound))
continue
}
fmt.Println(res.Ref.ID, res.Model.Title)
}
}
Output: tv-1234567 Дракон с подвижными сочленениями (пример) tv-404 not found: true
func (*Client) Limits ¶
Limits returns the account's per-minute and daily quota windows. It does not use the daily quota (it counts toward the per-minute limit like every method).
Example ¶
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
client, err := polyzon.NewClient()
if err != nil {
log.Fatal(err)
}
limits, err := client.Limits(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d of %d daily requests left, resets at %s\n", limits.Daily.Remaining, limits.Daily.Limit,
time.Unix(limits.Daily.ResetAt, 0).UTC().Format(time.RFC3339))
}
Output: 163 of 200 daily requests left, resets at 2026-10-10T00:00:00Z
func (*Client) Me ¶
Me returns the account and the token used for the request. It does not use the daily quota.
func (*Client) Search ¶
func (c *Client) Search(ctx context.Context, params SearchParams) (*SearchPage, error)
Search returns one page of models matching params. It costs one request of the daily quota (even when the API rejects the parameters).
Like every method, it retries connection errors, timeouts, HTTP 500/502/503/504 and 429 rate_limited up to the configured number of times (see WithMaxRetries), honouring Retry-After up to 60 seconds. A daily quota error (429 quota_exceeded) is returned at once.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
client, err := polyzon.NewClient()
if err != nil {
log.Fatal(err)
}
page, err := client.Search(context.Background(), polyzon.SearchParams{
Query: "дракон",
Sort: polyzon.SortPopular,
Free: true,
Sources: []string{polyzon.SourceThingiverse, polyzon.SourcePrintables},
})
if err != nil {
log.Fatal(err)
}
fmt.Println("total:", page.Total)
for _, item := range page.Items {
fmt.Printf("%s/%s %s (%s)\n", item.Source, item.ID, item.Title, item.License)
}
fmt.Println("daily requests left:", page.Meta.RateLimit.Remaining)
}
Output: total: 1873 thingiverse/tv-1234567 Дракон с подвижными сочленениями (пример) (cc-by-nc) daily requests left: 163
func (*Client) SearchAll ¶
func (c *Client) SearchAll(ctx context.Context, params SearchParams) iter.Seq2[SearchItem, error]
SearchAll iterates over all results of params, fetching pages lazily from params.Page (default 1) until a page reports no more results, comes back empty, or is page 100, the deepest the API serves. Every page costs one request of the daily quota; break out of the loop to stop fetching. On an error the iterator yields it once and stops.
for item, err := range client.SearchAll(ctx, polyzon.SearchParams{Query: "дракон", Size: 50}) {
if err != nil {
return err
}
fmt.Println(item.Title)
}
The API serves at most 2400 results per query (page × size).
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
client, err := polyzon.NewClient()
if err != nil {
log.Fatal(err)
}
// Each page costs one request of the daily quota; break to stop early.
for item, err := range client.SearchAll(context.Background(), polyzon.SearchParams{Query: "дракон", Size: 50}) {
if err != nil {
log.Fatal(err)
}
fmt.Println(item.Title)
}
}
Output: Дракон с подвижными сочленениями (пример)
type ItemStats ¶
type ItemStats struct {
Likes *int64 `json:"likes"`
Comments *int64 `json:"comments"`
Makes *int64 `json:"makes"`
// Collects counts saves to collections, or downloads where the source does
// not count saves.
Collects *int64 `json:"collects"`
}
ItemStats are the counters of a search item; nil means the source does not report the counter.
type License ¶
type License struct {
ID string `json:"id"` // a License* constant or another id
Raw string `json:"raw"` // the license text as named by the source, or ""
}
License is the license of a model card.
type Limits ¶
type Limits struct {
PerMinute QuotaWindow `json:"perMinute"` // every method
Daily QuotaWindow `json:"daily"` // search and model cards, UTC day
Meta Meta `json:"-"`
}
Limits are the account's quota windows. Quotas are per account, shared by all its tokens.
type Me ¶
type Me struct {
Account Account `json:"account"`
Token TokenInfo `json:"token"`
Meta Meta `json:"-"`
}
Me describes the account and the token used for the request.
type Meta ¶
type Meta struct {
// RequestID is the X-Request-ID response header, or "".
RequestID string
// RateLimit is the daily quota window from the x-ratelimit-* headers, or nil
// when the answer did not carry them.
RateLimit *RateLimit
}
Meta is the metadata of a successful answer. It is not part of the JSON body, so it is excluded from JSON encoding of the result types.
type Model ¶
type Model struct {
Source string `json:"source"`
ID string `json:"id"`
Title string `json:"title"`
URL string `json:"url"`
Description string `json:"description"`
Thumbnail string `json:"thumbnail"`
Images []string `json:"images"` // URLs on the source's CDN
Creator string `json:"creator"`
CreatorURL string `json:"creatorUrl"`
License *License `json:"license"` // nil when unknown
Price *Price `json:"price"` // nil when unknown
Formats []string `json:"formats"`
Tags []string `json:"tags"`
Category string `json:"category"`
Stats ModelStats `json:"stats"`
PublishedAt string `json:"publishedAt"` // ISO-8601 or ""
UpdatedAt string `json:"updatedAt"` // ISO-8601 or ""
// Copies are the same model on other sources.
Copies []ModelRef `json:"copies"`
Meta Meta `json:"-"`
}
Model is a model card. Optional text fields are "" when unknown.
type ModelOption ¶
type ModelOption func(*modelOptions)
ModelOption tunes Client.GetModel and Client.GetModels.
func WithConcurrency ¶
func WithConcurrency(n int) ModelOption
WithConcurrency sets how many requests Client.GetModels runs at once (default 4, at least 1). Client.GetModel ignores it.
type ModelRef ¶
ModelRef identifies a model: the source and the model id on it, as in polyzon.org/model/{source}/{id}.
type ModelResult ¶
ModelResult is the outcome of one reference in Client.GetModels: exactly one of Model and Err is set.
type ModelStats ¶
type ModelStats struct {
Likes *int64 `json:"likes"`
Comments *int64 `json:"comments"`
Makes *int64 `json:"makes"`
Collects *int64 `json:"collects"`
Downloads *int64 `json:"downloads"`
Views *int64 `json:"views"`
}
ModelStats are the counters of a model card; nil means unknown.
type Option ¶
type Option func(*settings) error
Option configures a Client in NewClient.
func WithAPIKey ¶
WithAPIKey sets the API token, overriding the POLYZON_API_KEY environment variable. Tokens are issued at https://polyzon.org/account/ (section «API»).
func WithBaseURL ¶
WithBaseURL sets the API endpoint, overriding the POLYZON_BASE_URL environment variable and DefaultBaseURL. It must be https, or http on a loopback host (localhost, 127.0.0.1, [::1]) for local testing, without credentials, query or fragment.
func WithHTTPClient ¶
WithHTTPClient makes the client send requests through a copy of httpClient, for a custom transport (CA bundle, mTLS, tracing). The copy never follows redirects, whatever httpClient.CheckRedirect says, since following one could leak the token to another origin. It cannot be combined with WithProxy or WithMaxConnections: configure the transport of httpClient instead. An *http.Transport with InsecureSkipVerify is rejected: add a custom CA to RootCAs rather than disabling certificate verification.
Example ¶
package main
import (
"crypto/tls"
"crypto/x509"
"log"
"net/http"
"os"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
// Trust a corporate CA in addition to the system roots. TLS verification
// itself cannot be turned off.
pool, err := x509.SystemCertPool()
if err != nil {
log.Fatal(err)
}
pem, err := os.ReadFile("corporate-ca.pem")
if err != nil {
log.Fatal(err)
}
pool.AppendCertsFromPEM(pem)
client, err := polyzon.NewClient(polyzon.WithHTTPClient(&http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{RootCAs: pool},
},
}))
if err != nil {
log.Fatal(err)
}
_ = client
}
Output:
func WithLogger ¶
WithLogger enables debug logging of requests: method, path with query, status, attempt, duration and retry delays. Headers, and so the token, are never logged. Records are emitted at slog.LevelDebug.
func WithMaxConnections ¶
WithMaxConnections limits the connections to the API kept open at once (default 10). Requests above the limit wait for a free connection.
func WithMaxRetries ¶
WithMaxRetries sets how many times a failed request is retried (default 2); 0 disables retries. Retried are connection errors, timeouts, HTTP 500/502/503/504 and 429 rate_limited, after the server's Retry-After (a wait over 60 seconds is not retried) or an exponential backoff with jitter. A spent daily quota (429 quota_exceeded) is never retried.
func WithProxy ¶
WithProxy routes requests through the proxy at proxyURL: http://, https:// or socks5:// (socks5h:// resolves names on the proxy), with optional user:password for Basic proxy authentication. Requests to https:// endpoints are tunnelled with CONNECT, so the proxy never sees the token.
WithProxy(nil) disables proxies. Without this option the standard environment variables HTTPS_PROXY, HTTP_PROXY and NO_PROXY apply (loopback hosts are never proxied through them).
Example ¶
package main
import (
"log"
"net/url"
"github.com/PolyzonOrg/polyzon-go"
)
func main() {
// Credentials in the URL become Basic proxy authentication. Requests to the
// https API are tunnelled with CONNECT, so the proxy never sees the token.
proxyURL, err := url.Parse("http://user:password@proxy.internal:3128")
if err != nil {
log.Fatal(err)
}
client, err := polyzon.NewClient(polyzon.WithProxy(proxyURL))
if err != nil {
log.Fatal(err)
}
_ = client
}
Output:
func WithTimeout ¶
WithTimeout sets the time limit of one request attempt, including reading the answer. The default is 30 seconds (10 of them at most for connecting). Use the context for an overall deadline across retries.
func WithUserAgent ¶
WithUserAgent appends suffix (for example "my-bot/2.1") to the default User-Agent "polyzon-go/<version> (go <version>; <os>/<arch>)". The suffix must be 1–256 printable ASCII characters.
type Price ¶
type Price struct {
// Type is PriceFree, PricePaid or PriceOpen (pay what you want).
Type string `json:"type"`
// Value is the amount, or nil when unknown.
Value *float64 `json:"value"`
// Currency is an ISO 4217 code, or "".
Currency string `json:"currency"`
// Display is the price formatted for people.
Display string `json:"display"`
}
Price is the price of a model.
type QuotaWindow ¶
type QuotaWindow struct {
Limit int64 `json:"limit"`
Used int64 `json:"used"`
Remaining int64 `json:"remaining"`
ResetAt int64 `json:"resetAt"` // start of the next window, Unix seconds
}
QuotaWindow is one quota window.
type RateLimit ¶
type RateLimit struct {
Limit int64 // requests per UTC day
Remaining int64 // requests left today
ResetAt int64 // next reset (00:00 UTC), Unix seconds
}
RateLimit is the daily quota window reported in the x-ratelimit-* headers.
type SearchItem ¶
type SearchItem struct {
Source string `json:"source"`
ID string `json:"id"`
Title string `json:"title"`
URL string `json:"url"` // the model page on the source site
Thumbnail string `json:"thumbnail"`
Creator string `json:"creator"`
// License is a license id (the License* constants), or "".
License string `json:"license"`
// Price is nil when unknown.
Price *Price `json:"price"`
Formats []string `json:"formats"`
Tags []string `json:"tags"`
Stats ItemStats `json:"stats"`
// PublishedAt is an ISO-8601 timestamp as reported by the source, or "".
PublishedAt string `json:"publishedAt"`
}
SearchItem is a model in search results. Optional text fields are "" when the source does not provide them.
type SearchPage ¶
type SearchPage struct {
// Query is the query as the server understood it.
Query string `json:"query"`
// CorrectedQuery is the spelling-corrected query actually searched, or "".
CorrectedQuery string `json:"correctedQuery"`
// DidYouMean is a suggested alternative query, or "".
DidYouMean string `json:"didYouMean"`
// Total is the number of matching models (see TotalRelation).
Total int64 `json:"total"`
// TotalRelation is TotalEq when Total is exact, TotalGte when it is a lower bound.
TotalRelation string `json:"totalRelation"`
Page int `json:"page"`
Size int `json:"size"`
// HasMore reports whether a next page exists within the 2400-result window.
HasMore bool `json:"hasMore"`
// Partial reports that part of the catalogue did not answer in time, so the
// results may be incomplete.
Partial bool `json:"partial"`
Items []SearchItem `json:"items"`
Meta Meta `json:"-"`
}
SearchPage is one page of search results.
type SearchParams ¶
type SearchParams struct {
// Query is the search text in Russian or English, up to 200 characters. Required.
Query string
// Page is the page number, 1–100 (default 1).
Page int
// Size is the number of models per page, 1–50 (default 20). Page × Size must
// not exceed 2400, else the API answers 400 page_too_deep.
Size int
// Sort is one of the Sort* constants (default SortRelevant).
Sort string
// Free restricts results to free models.
Free bool
// Sources restricts results to these sources (the Source* constants).
Sources []string
// Formats restricts results to these file formats, e.g. "stl", "3mf".
Formats []string
// Licenses restricts results to these license ids (the License* constants).
Licenses []string
// Lang is the language of titles and tags, LangRU (default) or LangEN.
Lang string
}
SearchParams are the parameters of Client.Search. Zero values are not sent, so the server defaults apply.
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
batch
command
Command batch fetches the model cards of a search page concurrently with GetModels and reports each result in input order.
|
Command batch fetches the model cards of a search page concurrently with GetModels and reports each result in input order. |
|
pagination
command
Command pagination walks every page of a search with SearchAll.
|
Command pagination walks every page of a search with SearchAll. |
|
proxy
command
Command proxy calls the API through an explicit proxy (http, https or socks5, with optional user:password) and prints the account the token belongs to.
|
Command proxy calls the API through an explicit proxy (http, https or socks5, with optional user:password) and prints the account the token belongs to. |
|
quickstart
command
Command quickstart searches the Polyzon catalogue, opens the first model card and prints the remaining daily quota.
|
Command quickstart searches the Polyzon catalogue, opens the first model card and prints the remaining daily quota. |