Upgrading

This page is for moving to a newer release, or to plycdn.com. What changed in each release, and what is new, is in the Release notes; this page says what to do about it.

You are on Read
Content Search before 1.6 (the earlier product name and package names) "Moving to plycdn.com" and "Content Search: moving to plycdn 1.6", then the 1.7 and 1.10 steps
Content Search 1.6 "Content Search: moving to 1.7", then "Content Search 1.10.0" in the release notes (upgrading from 1.6.0)
Storage & video 1.1.x (Plycdn.AspNetCore, @plycdn/angular and @plycdn/react with one entry point) "Storage & video 1.2.0" in the release notes: the packages are split by purpose and renamed

Moving to Content Search 1.11.0 or Storage & video 1.3.0 needs no change to your code: both are additions (delivery analytics, with PlycdnSignOptions.Tags and new reads). What is new is in "Added in Content Search 1.11.0 and Storage & video 1.3.0" in the release notes. Install the new package versions together, as before; analytics stays off for a bucket or library until you switch it on.

Storage & video 1.4.0 signs plycdn links in your process. If you stay on an earlier version, links for buckets with plycdn links are signed by plycdn (one extra call per link); upgrade when convenient. Content Search 1.12.0 changes nothing you call.

For help at any step, contact your plycdn representative.

1Moving to plycdn.com

Your server talks to the hosted API at https://api.plycdn.com/. That is the default of the Content Search package (Plycdn.ContentSearch.AspNetCore) and of the storage and video packages (Plycdn.AspNetCore.Storage and .Video), so the server-side change is to remove any Plycdn:ApiBaseUrl setting (environment variable Plycdn__ApiBaseUrl) that names an older host. Set it only if your plycdn contact gives you another HTTPS address:

{ "Plycdn": { "ApiKey": "<your key, from your secret store>" } }
  • Your API key does not change.
  • If your servers restrict outbound traffic, allow api.plycdn.com on port 443.
  • The browser packages never call the API directly; they call your backend, so they need no address.
  • Your dashboard is at https://plycdn.com/app, and the guides are at https://plycdn.com/docs.

2Content Search: moving to plycdn 1.6

Content Search now ships as plycdn. It is the same service with the same data: your library, indexes, collections, settings and API key all stay exactly as they are. What changes is the package names, the address your backend calls, and the route your backend serves to the browser.

There is no downtime and no deadline pressure. The previous address keeps working while you move, so you can make the change in your own release cycle. Nothing needs re-uploading or re-indexing.

You need your backend (.NET) developer, your frontend (Angular) developer, and someone who can sign in to the plycdn dashboard at https://plycdn.com/app, with the same email and password as before. Allow about an hour, plus your normal deployment.

What the 1.6.0 bundle contains

File What it is
Plycdn.ContentSearch.AspNetCore.1.6.0.nupkg The ASP.NET Core package (.NET 6-10)
plycdn-content-search-1.6.0.tgz The Angular package (Angular 13-22)
plycdn-content-search-react-1.6.0.tgz The React package, if you use React
(the guides) Published at https://plycdn.com/docs
SHA256SUMS Checksums, to confirm the files arrived intact

Do the numbered steps in order. Step 3 must follow the deployment of steps 1 and 2, because the new packages answer only on the new route.

Backend (ASP.NET Core)

Replace the package and rename what it provides. Nothing else in your code changes: every method, option and type keeps its name apart from the prefix.

Before After
Package Proctored.ContentSearch.AspNetCore Plycdn.ContentSearch.AspNetCore
AddProctoredContentSearch(...) AddPlycdnContentSearch(...)
AddProctoredAzureBlobStorage(...) AddPlycdnAzureBlobStorage(...)
Configuration section "Proctored" "Plycdn"
Environment variables Proctored__ApiKey and so on Plycdn__ApiKey, Plycdn__CallbackKey, Plycdn__CallbackSecret, Plycdn__Azure__ConnectionString
Organization claim proctored_organization_id plycdn_organization_id
Browser route /api/proctored-content/v1 /api/plycdn-content/v1 (served automatically)
Service address https://proctored.io/ https://api.plycdn.com/ (the default)
dotnet remove package Proctored.ContentSearch.AspNetCore
dotnet add package Plycdn.ContentSearch.AspNetCore --version 1.6.0 --source ./vendor/nuget
"Plycdn": {
  "ApiKey": "your existing API key",
  "CallbackKey": "your existing callback key",
  "CallbackSecret": "your existing callback secret"
}
  • Keep your API key, callback key and callback secret. They are unchanged.
  • Remove any ApiBaseUrl setting that names the old address. The package already defaults to https://api.plycdn.com/; set ApiBaseUrl only if your plycdn contact gives you another.
  • If your servers restrict outbound traffic, allow api.plycdn.com on port 443.
  • If a reverse proxy, gateway rule or firewall mentions /api/proctored-content/v1, change it to /api/plycdn-content/v1. Your PublicReadBaseUrl and PublicWriteBaseUrl settings stay as they are.

Frontend (Angular)

Before After
Package @proctored/content-search @plycdn/content-search
ProctoredContentSearchModule PlycdnContentSearchModule
<proctored-content-upload>, -search, -results, -playback, -document <plycdn-content-upload>, -search, -results, -playback, -document
apiBaseUrl: '/api/proctored-content/v1' apiBaseUrl: '/api/plycdn-content/v1'
CSS variable --proctored-accent --plycdn-accent (the --pcs-* variables are unchanged)
npm uninstall @proctored/content-search
npm install ./vendor/plycdn-content-search-1.6.0.tgz
import { PlycdnContentSearchModule } from '@plycdn/content-search';

PlycdnContentSearchModule.forRoot({ apiBaseUrl: '/api/plycdn-content/v1' })

A find-and-replace of proctored-content with plycdn-content and Proctored with Plycdn across your templates and modules covers almost all of it. Search results now come one card per file, with a jump-to link for each place it matched. Set [groupByFile]="false" on <plycdn-content-search> if you want one result per passage instead.

Update the callback address

Do this as soon as the new backend is live. Until then, leave it pointing at the old route.

  1. Sign in at https://plycdn.com/app.
  2. Open Content search → Indexing settings.
  3. Change the callback URL from https://YOUR_BACKEND/api/proctored-content/v1/source-callback to https://YOUR_BACKEND/api/plycdn-content/v1/source-callback.
  4. Save. The callback secret does not change.

If your organization has sub-organizations with their own storage settings, repeat this for each of them, using the organization switcher at the top left of the dashboard.

Storage (for highlighted PDFs)

In 1.6, a PDF result opens inside the component at the matched page, with the passage highlighted and the searched words marked. To do that, the browser reads the PDF directly, so your storage must allow cross-origin reads from your application, as it already does for Word and Excel files:

  • For Azure Blob Storage, add a CORS rule for each origin your application is served from: allow GET and HEAD, and expose Content-Length and Content-Range.
  • If your files are read through your own domain (your Application Gateway, via PublicReadBaseUrl), there is nothing to add: the browser reads them from its own origin.

Without the rule, nothing breaks: PDFs open in the browser's own viewer at the right page, just without the highlighting. No Content-Security-Policy change is needed for 1.6.

Storage event subscriptions

Only if you connected storage under Content search → Storage connectors and set up event notifications (for example Azure Event Grid). Open each connector in the dashboard, copy its notification address, which now begins https://api.plycdn.com/, and update the endpoint of your event subscription. The previous address keeps working in the meantime.

Check it works

  1. Sign-in and search: in your application, search for something you know is in your library. Results appear as one card per file.
  2. Playback: open a video result. It plays from the matched moment ("Play from 2:14").
  3. Documents: open a PDF result. It opens at the matched page, with the passage highlighted (after step 4).
  4. Upload: upload a small file. It reaches Ready to search in your application and Ready in the dashboard Library.
  5. Callback address: in the dashboard Library, open any file and press Re-index in the file's header (it is also in the row's menu in the list). It reaches Ready only by reading the file through your callback, so this confirms step 3.

If any step fails, the dashboard's Content search → Library health page shows what went wrong with each file, and the error code on a failed request matches the table in the API reference.

What else 1.6 brings

  • One result per file, with jump-to links for every match (time, page or slide).
  • The words you searched for are marked in results and inside opened documents.
  • PDFs render in place with the matched passage highlighted.
  • The result button says where it goes: "Play from 2:14", "Go to page 4", "Go to slide 3".
  • SCORM packages of every common shape are read, including slide-player courses whose content is in a data file, and launch pages that navigate between lesson pages.

If you need to go back

Reinstall your previous packages and set the callback URL (step 3) back to the old route. Your data is unaffected either way. The previous address stays available until we agree a date with you to retire it.

3Content Search: moving to 1.7

This release changed usage and billing, and has nothing to do with the rebrand above. The usage and billing changes below need no code change to keep working; the removals in the last bullet do, if you used what was removed.

  • .NET: no existing property changed type or name. Where an amount was a double?, it still is. New …Decimal properties (AmountDecimal, QuantityDecimal, IncludedDecimal, BillableDecimal, UnitPriceDecimal, TotalDecimal) sit alongside them for exact money and quantities; prefer those in new code. The double? ones are marked obsolete in their XML documentation only — no [Obsolete] attribute, so a build that treats warnings as errors is unaffected.
  • to is now inclusive. from=2026-09-01&to=2026-09-30 covers all of September. If your code requested to one day past what it wanted (to work around the old, exclusive behaviour), remove that adjustment.
  • dailyBudgetUsd is ignored. It is still accepted on PUT /settings and still returned by GET /settings, always as 0, for wire compatibility. What an organization can use is now controlled by your plan's quotas (GetUsageQuotasAsync / GET /usage/quotas), not a cost figure. Remove any code that reads or sets it for a real effect.
  • Sub-organization usage rolls up to the parent. Your account gets one statement, one allowance and one monthly minimum, covering every sub-organization; GetUsageAsync on the parent's key now returns an Organizations breakdown alongside the account total.
  • New month= request form. GetUsageAsync(org, year, month) reads a whole calendar month directly, in your account's time zone, without you computing from/to yourself.
  • Removed, and what to use instead. Renewing source access and reading settings are server actions only. Angular: ContentClient.refreshSource and ContentUploadComponent.renewSource are gone (the upload row's Check again asks for access, and your server renews it through the source-access callback). .NET: ContentController.RefreshSource and ContentController.Settings are gone, with the browser routes assets/{id}/refresh-source and settings; read settings on your server with GetSettingsAsync. Also, a plycdn API key in a URL or request body, deprecated in 1.7, is refused from 1.9: send it in the Authorization: ApiKey header. The Release notes list every removal since 1.6.
  • New: GetUsageDailyAsync, GetUsageQuotasAsync, ListStatementsAsync, GetStatementAsync and ExportStatementCsvAsync — see "How usage is counted" in the Integration guide and "What you have used" in the API reference.

For help at any step, contact your plycdn representative.