# Projects ## List workspace projects `client.Projects.List(ctx, query) (*ProjectsCursorPage[ProjectListResponse], error)` **get** `/projects` Returns projects in the requested workspace that are accessible to the authenticated public API key, ordered by recent activity. ### Parameters - `query ProjectListParams` - `WorkspaceID param.Field[string]` Workspace identifier - `Cursor param.Field[string]` Opaque cursor for fetching the next page - `Limit param.Field[int64]` Maximum number of results to return - `Query param.Field[string]` Search query ### Returns - `type ProjectListResponse struct{…}` - `CreatedAt float64` - `LastModified float64` - `Name string` Project name - `Origin string` Project origin - `ProjectID string` Project identifier - `WorkspaceID string` Workspace identifier ### Example ```go package main import ( "context" "fmt" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" ) func main() { client := flora.NewClient( option.WithAPIKey("My API Key"), ) page, err := client.Projects.List(context.TODO(), flora.ProjectListParams{ WorkspaceID: "ws_abc123", }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", page) } ``` #### Response ```json { "meta": { "next_cursor": "eyJvZmZzZXQiOjIwfQ", "total_estimate": 0 }, "projects": [ { "created_at": 0, "last_modified": 0, "name": "Spring Campaign", "origin": "api", "project_id": "prj_abc123", "workspace_id": "ws_abc123" } ] } ``` ## Create a project `client.Projects.New(ctx, body) (*ProjectNewResponse, error)` **post** `/projects` Creates a new Flora project in the requested workspace. Mutating public API requests support an optional Idempotency-Key header for client retries; duplicate keys within two hours return idempotency_duplicate. ### Parameters - `body ProjectNewParams` - `Name param.Field[string]` Project name - `WorkspaceID param.Field[string]` Workspace identifier ### Returns - `type ProjectNewResponse struct{…}` - `CreatedAt float64` - `LastModified float64` - `Name string` Project name - `Origin string` Project origin - `ProjectID string` Project identifier - `WorkspaceID string` Workspace identifier ### Example ```go package main import ( "context" "fmt" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" ) func main() { client := flora.NewClient( option.WithAPIKey("My API Key"), ) project, err := client.Projects.New(context.TODO(), flora.ProjectNewParams{ Name: "Spring Campaign", WorkspaceID: "ws_abc123", }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", project.ProjectID) } ``` #### Response ```json { "created_at": 0, "last_modified": 0, "name": "Spring Campaign", "origin": "api", "project_id": "prj_abc123", "workspace_id": "ws_abc123" } ``` ## Get a project `client.Projects.Get(ctx, projectID) (*ProjectGetResponse, error)` **get** `/projects/{projectId}` Returns metadata for a single project when it is accessible to the authenticated public API key. Missing and inaccessible projects both return 404. ### Parameters - `projectID string` Project identifier ### Returns - `type ProjectGetResponse struct{…}` - `CreatedAt float64` - `LastModified float64` - `Name string` Project name - `Origin string` Project origin - `ProjectID string` Project identifier - `WorkspaceID string` Workspace identifier ### Example ```go package main import ( "context" "fmt" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" ) func main() { client := flora.NewClient( option.WithAPIKey("My API Key"), ) project, err := client.Projects.Get(context.TODO(), "prj_abc123") if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", project.ProjectID) } ``` #### Response ```json { "created_at": 0, "last_modified": 0, "name": "Spring Campaign", "origin": "api", "project_id": "prj_abc123", "workspace_id": "ws_abc123" } ``` ## List project canvas nodes `client.Projects.ListNodes(ctx, projectID, query) (*CanvasNodesCursorPage[ProjectListNodesResponse], error)` **get** `/projects/{projectId}/nodes` Returns sanitized visible media nodes on a project canvas. The response omits raw graph documents, Liveblocks internals, raw Convex IDs, and unbounded node data blobs. ### Parameters - `projectID string` Project identifier - `query ProjectListNodesParams` - `Cursor param.Field[string]` Opaque cursor for fetching the next page - `Limit param.Field[int64]` Maximum number of results to return ### Returns - `type ProjectListNodesResponse struct{…}` - `NodeID string` Canvas node identifier - `Type ProjectListNodesResponseType` Canvas node media type - `const ProjectListNodesResponseTypeImage ProjectListNodesResponseType = "image"` - `const ProjectListNodesResponseTypeVideo ProjectListNodesResponseType = "video"` - `const ProjectListNodesResponseTypeAudio ProjectListNodesResponseType = "audio"` - `const ProjectListNodesResponseTypeText ProjectListNodesResponseType = "text"` - `AssetID string` Asset identifier - `Height int64` - `Label string` Canvas node label - `URL string` Canvas node output URL or text content - `Width int64` ### Example ```go package main import ( "context" "fmt" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" ) func main() { client := flora.NewClient( option.WithAPIKey("My API Key"), ) page, err := client.Projects.ListNodes( context.TODO(), "prj_abc123", flora.ProjectListNodesParams{ }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", page) } ``` #### Response ```json { "canvas_url": "https://example.com", "meta": { "next_cursor": "eyJvZmZzZXQiOjIwfQ", "total_estimate": 0 }, "nodes": [ { "node_id": "node_abc123", "type": "image", "asset_id": "asset_abc123", "height": 0, "label": "Logo", "url": "https://media.flora.ai/output.png", "width": 0 } ], "project_id": "prj_abc123" } ``` # Assets ## Attach an asset to a canvas `client.Projects.Assets.AttachAsset(ctx, assetID, body) (*ProjectAssetAttachAssetResponse, error)` **post** `/projects/{projectId}/assets/{assetId}/attach` Attaches an existing ready asset to a project canvas as a static media node. Mutating public API requests support an optional Idempotency-Key header for client retries; duplicate keys within two hours return idempotency_duplicate. ### Parameters - `assetID string` Asset identifier - `body ProjectAssetAttachAssetParams` - `ProjectID param.Field[string]` Project identifier ### Returns - `type ProjectAssetAttachAssetResponse struct{…}` - `AssetID string` Asset identifier - `CanvasURL string` Project canvas URL - `NodeID string` Canvas node identifier - `ProjectID string` Project identifier ### Example ```go package main import ( "context" "fmt" "github.com/florafauna-ai/flora-go" "github.com/florafauna-ai/flora-go/option" ) func main() { client := flora.NewClient( option.WithAPIKey("My API Key"), ) response, err := client.Projects.Assets.AttachAsset( context.TODO(), "asset_abc123", flora.ProjectAssetAttachAssetParams{ ProjectID: "prj_abc123", }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", response.AssetID) } ``` #### Response ```json { "asset_id": "asset_abc123", "canvas_url": "https://example.com", "node_id": "node_abc123", "project_id": "prj_abc123" } ```