Skip to content
Developers

From credential to signed document

This guide walks through the complete integration flow: upload a PDF, create the envelope, add a second signer, send it, receive webhook confirmation that everyone signed and download the sealed PDF. It continues where the quickstart ends. Each step shows the same call in curl, JavaScript and Java; the tab you choose stays selected across the page.

Requirements: the four environment variables from the quickstart (BBSIGN_BASE_URL, BBSIGN_TOKEN_URL, BBSIGN_CLIENT_ID, BBSIGN_CLIENT_SECRET), a PDF named contract.pdf and, for the JavaScript and Java tabs, a client built as in the quickstart.

Both SDKs fetch and refresh tokens automatically. The explicit token is needed for curl and for the upload in step 2, which uses plain HTTP. A token is valid for 300 s.

Ventana de terminal
TOKEN=$(curl -s -X POST "$BBSIGN_TOKEN_URL" \
-d grant_type=client_credentials \
-d client_id="$BBSIGN_CLIENT_ID" \
-d client_secret="$BBSIGN_CLIENT_SECRET" | jq -r .access_token)

POST /api/v1/documents takes multipart with one part, file. It accepts application/pdf up to 50 MB. The response is an UploadedDocumentResponse; keep its id. A document that is not attached to an envelope within 24 h is deleted.

Ventana de terminal
DOCUMENT_ID=$(curl -s -X POST "$BBSIGN_BASE_URL/api/v1/documents" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@contract.pdf;type=application/pdf" | jq -r .id)

The generated SDK methods send JSON, so the multipart uploads in the JavaScript and Java tabs use the platform HTTP client (okhttp is already a dependency of the Java SDK). You can also attach a file to an existing draft with POST /api/v1/envelopes/{id}/documents, with the same part name.

Send the document id in documentIds. title is the only required field; sending the envelope requires at least one signer and one document.

Ventana de terminal
ENVELOPE_ID=$(curl -s -X POST "$BBSIGN_BASE_URL/api/v1/envelopes" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"Service agreement\",
\"documentIds\": [\"$DOCUMENT_ID\"],
\"otpRequired\": true,
\"signers\": [{\"email\": \"ana@example.com\", \"name\": \"Ana Perez\", \"signOrder\": 1}]
}" | jq -r .id)

You can add signers while the envelope is in DRAFT. signOrder applies when sequentialSigning is true; otherwise every signer receives a link at the same time.

Ventana de terminal
curl -s -X POST "$BBSIGN_BASE_URL/api/v1/envelopes/$ENVELOPE_ID/signers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "luis@example.com", "name": "Luis Gomez", "signOrder": 2}'

On send, the documents and signers become fixed, each signer is emailed a link valid for 72 h by default, and envelope.sent is emitted. The response is a SendResponse with each signer’s signing tokens.

Ventana de terminal
curl -s -X POST "$BBSIGN_BASE_URL/api/v1/envelopes/$ENVELOPE_ID/send" \
-H "Authorization: Bearer $TOKEN"

Register a webhook in Settings, tab Webhooks, subscribed to envelope.completed. When the last signer signs, bb-sign sends a signed event to your URL. Verify the signature over the raw body, respond 2xx and then process the event. The payload contains the envelope id and status; the document is retrieved in step 7. Webhooks describes delivery and retries.

POST /webhooks/bb-sign HTTP/1.1
Content-Type: application/json
X-BBSign-Event-Id: 3f8c1e2a-7d44-4b1a-9c0e-5a6b7c8d9e0f
X-BBSign-Event-Type: envelope.completed
X-BBSign-Signature: t=1760000000,v1=5f1a...
{"id":"3f8c1e2a-7d44-4b1a-9c0e-5a6b7c8d9e0f","type":"envelope.completed","apiVersion":"2026-08-09",
"createdAt":"2026-10-10T14:22:31Z","data":{"envelope":{"id":"...","title":"Service agreement",
"status":"COMPLETED","createdAt":"...","expiresAt":null}}}

7. List the documents and download the signed PDF

Section titled “7. List the documents and download the signed PDF”

GET /api/v1/envelopes/{id}/documents returns each document with a downloadUrl (the original) and, once the envelope is COMPLETED, a signedUrl (the sealed copy). Both are presigned links valid for 3,600 s, and they are null if the credential does not hold document:download in the envelope’s workspace. Treat them as secrets: they give access to the file without a token.

Ventana de terminal
SIGNED_URL=$(curl -s "$BBSIGN_BASE_URL/api/v1/envelopes/$ENVELOPE_ID/documents" \
-H "Authorization: Bearer $TOKEN" | jq -r '.[0].signedUrl')
curl -s -o contract-signed.pdf "$SIGNED_URL"

Archive the documents you download: bb-sign keeps signed documents for a fixed period, and conservation after that is the organization’s responsibility. See Scope and retention.

429 and 503 are also retried for POST, because they indicate the server did not process the request.

The envelope in this walkthrough was filed in General because no workspaceId was sent. A credential accesses the workspaces an admin assigned to it; GET /api/v1/workspaces lists them, and each EnvelopeResponse includes workspaceId and workspaceName. Envelopes in workspaces the credential cannot read return 404 and do not appear in lists.