Developer
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Key-Value Store
Custom Entity Store
SQL
Object Store (EAP)
Last updated Feb 13, 2025

Storing, downloading, and deleting large objects

Forge Object Store is now available as part of our Early Access Program (EAP). To start testing this feature, sign up using this form.

Forge Object Store is an experimental feature offered for testing and feedback purposes. This feature is unsupported and subject to change without notice. Do not use Forge Object Store in apps that handle sensitive information, including personal data and customer data.

For more details, see Forge EAP, Preview, and GA.

 

The Forge Object Store API lets you upload, download, and manage large items (like data objects and media files) directly from your app. This API also lets you create pre-signed URLs for download and upload requests.

To start using the Forge Object Store, add the required package (@forge/os) to your project first:

1
2
npm install @forge/os 

Then, import the package to your app, as follows:

1
2
import os from '@forge/os' 

To integrate the Forge Object Store with your app's frontend, use the objectStore bridge methods.

Limitations

The Forge Object Store has the following limitations during the EAP:

  • Storage limits: Objects can be up to 50 MB each, with a total storage cap of 1 GB across all objects.

  • Time-to-Live (TTL): Objects have a default TTL of 90 days. Custom TTLs can be set but must be greater than 1 second and can't exceed 90 days. This limitation will only be in effect for the EAP.

    All objects will be deleted at the end of the EAP. Atlassian will provide notice before the end of the EAP to ensure you have time to download any stored data.

  • Accessing objects in UI: Direct object upload and download links for UI components are not supported and must be managed through Forge functions. File uploads or downloads in UI Kit must be handled through a Frame component, which acts as a container for a Custom UI application.

  • Pre-signed URLs: Pre-signed URLs are only available in the UI Kit Frame component or Custom UI. Support for resolver/Lambda is in progress and will be available soon.

  • Production deployments: The EAP is only for testing purposes and deployment to production will not be available.

Get metadata

Retrieve the metadata for objects stored in the Forge-hosted object store using the get method.

This method works as follows:

  • key (string): The unique identifier for the object metadata to retrieve.
  • Returns: The objectReference if found, or undefined if the object does not exist.

To integrate with the frontend, use the objectStore bridge API's get method.

Method signature

1
2
os.get(key: string): Promise<ObjectReference | undefined>;

interface ObjectReference {
  key: string;
  checksum: string;
  size: number;
  createdAt?: string;
  currentVersion?: string;
} 

Example

1
2
export const getObjectRef = async (key: string): Promise<ObjectReference | undefined> => {
  try {
    const objectRef = os.get(key);
    if (objectRef === undefined) {
      console.info('Object was not found',  { key })
    }
    return objectRef
  } catch (error) {
    console.error('Error getting object reference', JSON.stringify(error))
  }
};

Delete

Remove objects from the Forge-hosted object store using the delete method.

The delete method works as follows:

  • key (string): The unique identifier for the object to delete.

To integrate with the frontend, use the objectStore bridge API's deleteObjects method.

Method signature

1
2
os.delete(key: string): Promise<void>;

Example

1
2
export const deleteObject = async (key: string): Promise<void> => {
  try {
    await os.delete(key)
  } catch (error) {
    console.error('Error deleting object', JSON.stringify(error))
  }
}

Create pre-signed download URL

Create a URL with temporary permissions to download a specific object to a client using the createDownloadUrl method. The created URL will expire after 1 hour.

To integrate with the frontend, use the objectStore bridge API's download method.

Don’t store pre-signed URLs in a global context. Doing this could potentially let customer data persist across app invocations between different installations. See Developer responsibilities for related information.

Method signature

When generating a pre-signed download URL, you need to include the key (string) in your request. The createDownloadUrl method uses this as a unique identifier for your URL.

The method will then return a PresignedUrlResponse. The object's content-type will be what was specified
via the pre-signed upload URL; otherwise, the content-type will be application/octet-stream.

1
2
os.createDownloadUrl(key: string): Promise<PresignedUrlResponse | undefined>

interface PresignedUrlResponse {
  url: string;
}

Use a GET operation to download an object via the returned PresignedUrlResponse. This GET operation accepts the Range header to download parts of the object. For example, the following header will request the first 500 bytes of the object:

1
2
Range: bytes=0-499

Example

1
2
export const createDownloadUrl = async (key: string): Promise<PresignedUrlResponse | undefined> => {
  try {
    return await os.createDownloadUrl(key);
  } catch (error) {
    console.error('Error creating pre-signed download URL', JSON.stringify(error))
  }
};

export const downloadUsingUrl = async (objectId: string): Promise<any> => {
  const { url } = await createDownloadUrl(objectId);
  if (url) {
    const response = await fetch(url);
    if (response.ok) {
      return response;
    } else {
      console.error('Failed to download object: ', objectId);
    }
  }
};

Create pre-signed upload URL

Create a URL with temporary permissions to upload a single object using the createUploadUrl method. Pre-signed upload URLs can only be used for objects under 1GB. The created URL will expire after 1 hour.

To integrate with the frontend, use the objectStore bridge API's upload method.

Don’t store pre-signed URLs in a global context. Doing this could potentially let customer data persist across app invocations between different installations. See Developer responsibilities for related information.

Method signature

When generating a pre-signed upload URL through createUploadUrl, your request must include an UploadUrlBody containing the properties of the file you’re uploading. These properties are:

  • key: The unique identifier for the object.
  • length: The byte size of the object.
  • checksum: Hash digest of the file content, encoded as base64. Used to verify data integrity.
  • checksumType: Algorithm used to generate the checksum.
  • ttlSeconds (optional): Allows you to set a custom TTL for and object.
  • overwrite (optional): Indicates whether to replace an existing object with the same key. This defaults to true.

The method will then return a PresignedUrlResponse.

1
2
os.createUploadUrl(body: UploadUrlBody): Promise<PresignedUrlResponse>

interface UploadUrlBody {
  key: string;
  length: number;
  checksum: string;
  checksumType: 'SHA1' | 'SHA256' | 'CRC32' | 'CRC32C';
  ttlSeconds?: number;
  overwrite?: boolean;
}

interface PresignedUrlResponse {
  url: string;
}

Use a PUT operation to upload an object via the returned PresignedUrlResponse. This PUT operation does not require any additional headers.

However, we strongly advise that you send the content-type header, as this value will be retained on the object and returned when downloaded. By default, objects will use application/octet-stream as their content-type header.

Example

1
2
export const createUploadUrl = async (key: string, object: any, objectLength: number, ttlSeconds?: number): Promise<PresignedUrlResponse | undefined> => {
  try {
    const bufferedObject = Buffer.from(object)
    // Create SHA256 checksum from buffer
    const checksum = crypto.createHash('sha256').update(bufferedObject).digest('base64');
    const body: UploadUrlBody = {
      key: key,
      length: objectLength,
      checksum,
      checksumType: 'SHA256',
      ttlSeconds,
      overwrite: true,
    };
    const resp = await os.createUploadUrl(body);
    return resp;
  } catch (error) {
    console.error('Error creating pre-signed upload URL', JSON.stringify(error))
  }
};

export const uploadUsingUrl = async (uploadObjectProperties: any): Promise<void> => {
  const { objectId, object, objectLength, ttlSeconds } = uploadObjectProperties
  const { url } = await createUploadUrl(objectId, object, objectLength, ttlSeconds);
  if (url) {
    const response = await fetch(url, {
      method: 'PUT',
      headers: {
        'content-type': 'application/octet-stream', // or the actual content type of your object
      },
      body: object,
    });
    if (!response.ok) {
      console.error('Failed to upload object: ', objectId);
    }
  }
};

Deprecated methods

The following methods are now deprecated, and will be removed once Forge Object Store transitions to Preview.

Upload/Update object

Store large files or media efficiently from your app using the Forge-hosted storage. Use the put method to upload an object with the following parameters:

  • key (string): A unique identifier for the object being stored. If an object already exists with the same key, the new upload will add a new version of the object, effectively functioning as an update operation.
  • object (any): The data to be stored, which is buffered internally for efficient handling.
  • ttlSeconds (number): Allows you to set a custom TTL for an object. If no TTL is set, the object's TTL will default to 90 days. Custom TTLs must be greater than 1 second and can't exceed 90 days.

Method signature

1
2
os.put(key: string, object: any, ttlSeconds?: number): Promise<void>;

Example

1
2
export const uploadObject = async (key: string, object: any, ttlSeconds?: number): Promise<void> => {
  try {
    const bufferedObject = Buffer.from(object)
    await os.put(key, bufferedObject, ttlSeconds)
  } catch (error) {
    console.error('Error uploading object', JSON.stringify(error))
  }
}

Download

Retrieve the data of the latest version of an object stored in the Forge Object Store using the download method.

The download method works as follows:

  • key (string): The unique identifier for the object to download.
  • Returns: A Buffer containing the latest object data if it exists, or undefined if the object is not found.

Method signature

1
2
os.download(key: string): Promise<Buffer | undefined>;

Example

1
2
export const downloadObject = async (key: string): Promise<Buffer | undefined> => {
try {
    const object = os.download(key);
    if (object === undefined) {
      console.info('Object was not found',  { key })
    }
    return object
  } catch (error) {
    console.error('Error downloading object', JSON.stringify(error))
  }
}

EAP Feedback

As part of the EAP, your feedback is invaluable in shaping the future of this feature. We encourage you to explore Forge Object Store's capabilities and share your insights to help us refine and enhance this service.

Rate this page: