Using an AI coding assistant? Copy this prompt
Build a SureDocs integration following https://developer.suredocs.ie/llms.txtYour assistant reads the rest from this site. Keep your refresh token out of the chat: put it in the environment
variable SUREDOCS_REFRESH_TOKEN, where the code it writes should read it from.
This page takes you from nothing to a PDF filed with a brokerage, using curl. Every value in it that you
would replace is obviously fake, and nothing here is a real credential.
What you need
- An integration id and a refresh token. The integration is your software's identity with us, and its
id looks like
int_example_a1b2c3d4. The refresh token is the long-lived secret we issued for it. We hand both to you through a one-time share that expires; see Authentication for how to keep the refresh token safe. - A brokerage that has granted your integration access. Try everything against the test broker, whose
id is
test, before you use a real brokerage. Ask us to grant your integration access to it. - A PDF, no larger than 24,000,000 bytes, a JPEG or PNG image, no larger than 10,000,000 bytes, a UTF-8 text file such as a call transcript, no larger than 2,000,000 bytes, or a WAV or MP3 recording such as a recorded call, no larger than 24,000,000 bytes. Each is stored as what it is, never converted to another type; see the API reference for the full, current list of accepted types.
curlandjq, or any HTTP client you prefer.
The model in one paragraph
An integration is your software. We issue it a refresh token. You exchange the refresh token for an access token, which lasts 1 hour and acts for one brokerage only. The brokerage must have given your integration a grant, which lists what it may do, and the access token carries the scopes both agree on. You send the access token with each call. The brokerage is named in the token and never in a URL, so a call cannot be aimed at another brokerage by changing a path.
integration -> refresh token -> access token -> the brokerage's grant
1. Set your credentials
export CLIENT_ID='int_example_a1b2c3d4'
export REFRESH_TOKEN='<the refresh token we gave you>'
export BROKER_ID='test'
2. Exchange the refresh token for an access token
curl -sS https://api.suredocs.ie/oauth/token \
--data-urlencode grant_type=refresh_token \
--data-urlencode client_id="$CLIENT_ID" \
--data-urlencode refresh_token="$REFRESH_TOKEN" \
--data-urlencode broker_id="$BROKER_ID" > token.json
The response looks like this:
{
"access_token": "<the access token, a long opaque string>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<the NEXT refresh token>",
"scope": "upload_file"
}
The refresh token in the response replaces the one you sent, and the one you sent no longer works. Store the new one before you do anything else. In real code you write it to your secret store first and only then use the access token. Authentication explains why, and what to do when a response is lost.
For this walkthrough, keep both in shell variables. Run these two lines only when the response is the one
above; after an error they would overwrite REFRESH_TOKEN with null:
export ACCESS_TOKEN=$(jq -r .access_token token.json)
export REFRESH_TOKEN=$(jq -r .refresh_token token.json)
If the request is refused, the body says why. invalid_grant means the refresh token is no longer usable;
invalid_target means the brokerage does not exist or has not granted your integration access. Every error
is listed in Authentication.
3. Upload a PDF
The file travels base64-encoded inside a JSON body. Encode it into a file first, because a large PDF is too big to pass on a command line:
base64 -w0 example.pdf > example.pdf.b64 # on macOS: base64 -i example.pdf -o example.pdf.b64
jq -n --rawfile content example.pdf.b64 \
'{filename: "example.pdf", contentType: "application/pdf", contentBase64: $content}' |
curl -sS https://api.suredocs.ie/files/v1 \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
--data-binary @-
The answer says the document was stored:
{
"status": "stored",
"fileId": "file_0123456789abcdef0123456789abcdef",
"requestId": "2f4a5f8e-9d3c-4b6e-8f4a-0c5b1e7d2a90"
}
Send the same request again and the answer is a duplicate. Nothing more is stored, so a retry after a timeout is always safe:
{
"status": "duplicate",
"fileId": "file_0123456789abcdef0123456789abcdef",
"matchedOn": ["filename", "content"],
"duplicateOf": "file_0123456789abcdef0123456789abcdef",
"requestId": "6c1d9a52-3f0b-47a8-a1de-5b7f2c4e8d13"
}
A duplicate is decided by content first: the same bytes are a duplicate under any name. We compare with
documents stored in the last 18 days and do not remember for longer, so the same bytes sent
after that are stored again. The same name with different bytes is a different document. It is stored under
a name derived from yours, and the answer says so in storedAs and nameCollisionWith.
A refusal has one shape whatever went wrong. reason is what your code branches on:
{
"status": 415,
"reason": "unsupported_file_type",
"message": "contentType must be one of application/pdf, image/jpeg, text/plain, image/png, audio/wav, audio/mpeg.",
"requestId": "0b8e3d17-c6a4-4f29-9e5d-7a1c3b5f2e60"
}
What the brokerage sees
The document is classified like any other and reaches the brokerage as a new item in its SureDocs list. It is from Partner upload, and its type is Unknown. It carries the filename you sent, so the brokerage sees that name, and only that brokerage does. Do not put in a filename anything you would not want its staff to read. A brokerage finds the document by typing "Partner upload" in the list's search box, as it would find one from any insurer. Opening it shows what you sent: a PDF opens as a PDF, an image as an image, a text file as text and a recording as a recording, because none is converted into another type on the way in.
Where next
- Renew the access token before it expires, not before every call: it lasts 1 hour. The rules for doing that safely are in Authentication.
- Read Rate limits before you build a loop around the upload.
- Every field, limit and error of the upload is in the API reference.