# Visualization

## Get package visualization metadata with timeline

> Returns metadata for a repository/branch including the commit timeline.\
> &#x20;       The timeline contains commit IDs, timestamps, and ordering — suitable for building\
> &#x20;       a timeline slider in the UI without loading snapshot data.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/metadata":{"get":{"operationId":"VisualizationController_getMetadata","summary":"Get package visualization metadata with timeline","description":"Returns metadata for a repository/branch including the commit timeline.\n        The timeline contains commit IDs, timestamps, and ordering — suitable for building\n        a timeline slider in the UI without loading snapshot data.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"branch","required":true,"in":"query","schema":{"type":"string"}},{"name":"releaseConfigPath","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Metadata with timeline if available, null otherwise"},"400":{"description":"Missing required parameters"},"403":{"description":"Forbidden - Requires role: member, application"},"404":{"description":"Project not found"}},"tags":["Visualization"]}}}}
```

## Upsert visualization metadata

> Creates or updates visualization metadata for a repository/branch.\
> &#x20;       Returns the metadataId needed for batch commit uploads.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/metadata":{"put":{"operationId":"VisualizationController_upsertMetadata","summary":"Upsert visualization metadata","description":"Creates or updates visualization metadata for a repository/branch.\n        Returns the metadataId needed for batch commit uploads.","parameters":[],"responses":{"200":{"description":"Metadata upserted, returns metadataId"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Visualization"]}}}}
```

## Get paginated commit snapshots

> Returns commit snapshots with pagination. Each commit contains its\
> &#x20;       package snapshots (\~1-5KB). Default limit is 50, max is 200.\
> &#x20;       Results are ordered newest-first by commit\_order.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/commits":{"get":{"operationId":"VisualizationController_getCommitsPaginated","summary":"Get paginated commit snapshots","description":"Returns commit snapshots with pagination. Each commit contains its\n        package snapshots (~1-5KB). Default limit is 50, max is 200.\n        Results are ordered newest-first by commit_order.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"branch","required":true,"in":"query","schema":{"type":"string"}},{"name":"offset","required":false,"in":"query","schema":{"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"Paginated commit snapshots"},"403":{"description":"Forbidden - Requires role: member, application"},"404":{"description":"No visualization data or project not found"}},"tags":["Visualization"]}}}}
```

## Batch upsert commit snapshots

> Upserts a batch of commit snapshots for a given metadataId.\
> &#x20;       The engine sends batches of \~100 commits at a time.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/commits/batch":{"post":{"operationId":"VisualizationController_upsertCommitsBatch","summary":"Batch upsert commit snapshots","description":"Upserts a batch of commit snapshots for a given metadataId.\n        The engine sends batches of ~100 commits at a time.","parameters":[],"responses":{"200":{"description":"Commits upserted"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Visualization"]}}}}
```

## Get existing commit IDs for incremental collection

> Returns the list of commit IDs already stored for a repository/branch.\
> &#x20;       The engine uses this to skip commits that have already been processed.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/commits/existing":{"get":{"operationId":"VisualizationController_getExistingCommitIds","summary":"Get existing commit IDs for incremental collection","description":"Returns the list of commit IDs already stored for a repository/branch.\n        The engine uses this to skip commits that have already been processed.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"branch","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Existing commit IDs and metadataId"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Visualization"]}}}}
```

## Get snapshots for a single commit

> Returns the package snapshots for a specific commit ID.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/commits/{commitId}":{"get":{"operationId":"VisualizationController_getCommitById","summary":"Get snapshots for a single commit","description":"Returns the package snapshots for a specific commit ID.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"branch","required":true,"in":"query","schema":{"type":"string"}},{"name":"commitId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Commit snapshots"},"403":{"description":"Forbidden - Requires role: member, application"},"404":{"description":"Commit or project not found"}},"tags":["Visualization"]}}}}
```

## Get visualization status

> Check the current status of package visualization for a repository/branch.\
> &#x20;       Returns one of: \`never\_ran\`, \`generating\`, \`available\`, or \`failed\`.\
> &#x20;       Safe to poll — does not trigger any work.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/status":{"get":{"operationId":"VisualizationController_getStatus","summary":"Get visualization status","description":"Check the current status of package visualization for a repository/branch.\n        Returns one of: `never_ran`, `generating`, `available`, or `failed`.\n        Safe to poll — does not trigger any work.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"branch","required":true,"in":"query","schema":{"type":"string"}},{"name":"releaseConfigPath","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Current visualization status"},"403":{"description":"Forbidden - Requires role: member, application"}},"tags":["Visualization"]}}}}
```

## Trigger visualization refresh

> Triggers a new visualization data collection via Hatchet workflow.\
> &#x20;       Returns a task execution ID for tracking.\
> &#x20;       Returns 409 Conflict if a visualization job is already running for this repository/branch.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.3.0"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/visualization/packages/refresh":{"post":{"operationId":"VisualizationController_refreshVisualization","summary":"Trigger visualization refresh","description":"Triggers a new visualization data collection via Hatchet workflow.\n        Returns a task execution ID for tracking.\n        Returns 409 Conflict if a visualization job is already running for this repository/branch.","parameters":[{"name":"repositoryIdentifier","required":true,"in":"query","schema":{"type":"string"}},{"name":"branch","required":true,"in":"query","schema":{"type":"string"}},{"name":"releaseConfigPath","required":true,"in":"query","schema":{"type":"string"}},{"name":"maxCommits","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"202":{"description":"Refresh triggered"},"403":{"description":"Forbidden - Requires role: member, application"},"409":{"description":"Visualization already in progress"}},"tags":["Visualization"]}}}}
```
