diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9335b7b..770765d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2.4.0] - 2026-11-05
+
+### Added
+
+- Add `organizations().downloadManifiestoZipUrl(String id)` to obtain a temporary URL for downloading the signed Carta Manifiesto ZIP associated with the organization's certificate RFC.
+
## [2.3.0] - 2026-10-07
### Added
diff --git a/pom.xml b/pom.xml
index 40a1b17..4d38ac0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
io.facturapi
facturapi-java
- 2.3.0
+ 2.4.0
facturapi-java
Official Java SDK for Facturapi
https://github.com/facturapi/facturapi-java
diff --git a/src/main/java/io/facturapi/models/SignedDownloadUrl.java b/src/main/java/io/facturapi/models/SignedDownloadUrl.java
new file mode 100644
index 0000000..c43fa70
--- /dev/null
+++ b/src/main/java/io/facturapi/models/SignedDownloadUrl.java
@@ -0,0 +1,44 @@
+package io.facturapi.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import java.time.Instant;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SignedDownloadUrl {
+ private String url;
+ private Instant expiresAt;
+ private String contentType;
+ private String filename;
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public Instant getExpiresAt() {
+ return expiresAt;
+ }
+
+ public void setExpiresAt(Instant expiresAt) {
+ this.expiresAt = expiresAt;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = filename;
+ }
+}
diff --git a/src/main/java/io/facturapi/resources/OrganizationsResource.java b/src/main/java/io/facturapi/resources/OrganizationsResource.java
index c5fb0de..b0923f0 100644
--- a/src/main/java/io/facturapi/resources/OrganizationsResource.java
+++ b/src/main/java/io/facturapi/resources/OrganizationsResource.java
@@ -14,6 +14,7 @@
import io.facturapi.models.OrganizationUserAccess;
import io.facturapi.models.SearchResult;
import io.facturapi.models.Series;
+import io.facturapi.models.SignedDownloadUrl;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@@ -134,6 +135,17 @@ public Organization deleteCertificate(String id) {
return delete("/organizations/" + id + "/certificate", null, Organization.class);
}
+ /**
+ * Gets a temporary URL for downloading the signed Carta Manifiesto ZIP.
+ */
+ public SignedDownloadUrl downloadManifiestoZipUrl(String id) {
+ return get(
+ "/organizations/" + id + "/manifiesto/download-url",
+ null,
+ SignedDownloadUrl.class
+ );
+ }
+
/**
* Permanently removes an organization.
*/
diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java
index 7656160..4656fe5 100644
--- a/src/test/java/io/facturapi/FacturapiResourcesTest.java
+++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java
@@ -372,6 +372,30 @@ void organizationCertificateUploadsAcceptBytes() {
assertEquals("/v2/organizations/org_1/certificate", httpClient.requests().get(0).uri().getPath());
}
+ @Test
+ void organizationManifiestoZipDownloadUrlIsTyped() {
+ StubHttpClient httpClient = new StubHttpClient();
+ httpClient.enqueueJson(
+ 200,
+ "{\"url\":\"https://storage.googleapis.com/signed-download\",\"expires_at\":\"2030-01-01T00:00:00Z\",\"content_type\":\"application/zip\",\"filename\":\"manifiesto_AAA010101AAA.zip\"}"
+ );
+
+ Facturapi sdk = new Facturapi(
+ FacturapiConfig.builder("sk_test")
+ .httpClient(httpClient.client())
+ .build()
+ );
+
+ var response = sdk.organizations().downloadManifiestoZipUrl("org_1");
+
+ assertEquals("application/zip", response.getContentType());
+ assertEquals("manifiesto_AAA010101AAA.zip", response.getFilename());
+ assertEquals(Instant.parse("2030-01-01T00:00:00Z"), response.getExpiresAt());
+ var request = httpClient.requests().get(0);
+ assertEquals("GET", request.method());
+ assertEquals("/v2/organizations/org_1/manifiesto/download-url", request.uri().getPath());
+ }
+
@Test
void sdkExposesAccessorBasedSurface() {
StubHttpClient httpClient = new StubHttpClient();