Appearance
Pushing your portfolio
The External API v2 has one write channel for portfolio data: POST /patents/sync. You push 1..N patents as they exist in your IPMS, and Renewr decides, item by item, what applies immediately and what waits for a review. Nothing you push can silently corrupt renewal deadlines: any change that could re-drive the annuity computation is held for a human decision before it touches the live patent. That triage model has its own page, Change requests & review; this guide covers the mechanics of the call itself.
Pushing needs the patents:write scope on your API key. The channel covers patents only.
The first load goes through the Renewr team
This channel is built for keeping Renewr in sync with your IPMS once your portfolio is in. For the initial load, hand an export to the Renewr team instead: operators import and check it as part of onboarding, which avoids pushing your whole book through the review queue as creations. Details in the cookbook.
The request
A push is a single POST carrying an optional idempotence reference and a list of items:
bash
curl -X POST "https://api.renewr.example/api/v2/external/patents/sync" \
-H "x-api-key: $RENEWR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalImportRef": "ipms-2026-08-07-0001",
"items": [
{ "providerId": "ACME-2021-0042", "title": "Heat exchanger with corrugated fins (amended claims)" },
{ "renewrPatentId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "grantDate": "2024-03-13" }
]
}'Items use the same field names and enum values you read back from GET /patents: office, status, filingRoute, applicationNumber, and so on. What you pull and what you push share one vocabulary, so a mirror table in your integration needs no second mapping. The full field list is in the reference.
Three properties define the contract:
- Every item is an upsert. The same request can update one patent and propose the creation of another; you never tell the API which is which. Identity resolution decides (next section).
- Items are processed independently. One malformed item is rejected alone, with its own reason; the others proceed. A request is never refused as a whole for one bad item, and never for its size.
- A partial item is a partial update. Sending only the fields that changed is supported: an omitted field leaves the live value untouched, and an explicit
nullproposes clearing the field. Sending the full record is just as valid; Renewr diffs it against the live patent, so unchanged fields count for nothing.
How an item attaches to a patent
Each item carries its identity in one or two fields: providerId (your own reference, the one Renewr echoes back everywhere) and renewrPatentId (the Renewr UUID). Resolution follows one rule: renewrPatentId wins when both are present.
| Identity provided | Renewr finds | Action |
|---|---|---|
renewrPatentId (alone or with providerId) | The patent exists in your portfolio | Update of that patent |
providerId alone | A patent carries this reference | Update of that patent |
providerId alone | No patent carries this reference | Proposed creation |
| Neither | Rejected: no identity provided |
Two guardrails to know:
- An unknown
renewrPatentIdnever creates. The item is rejected. Creation is reserved toproviderId, so a typo in a UUID cannot spawn a duplicate patent. - Conflicting identities reject. If
renewrPatentIdandproviderIdresolve to two different patents, the item is rejected rather than guessing.
What you can send
Every field of the patent read model is writable except the identifiers and the fields Renewr owns. Eight internal fields (id, clientId, holderId, agentBranchId, isArchived, version, createdAt, updatedAt) and the officialNumbers block are forbidden: an item containing one is rejected with Forbidden field: <name>, before anything else is looked at. See Your numbers and Renewr's numbers for why officialNumbers is off limits.
Write validation is stricter than what reads tolerate:
- Dates must be strict
YYYY-MM-DD. A timestamp or2026-1-5rejects the item. officemust be an uppercase 2-letter code (WO,EP,EA, or an ISO 3166-1 national office code).- Enum values must be known ones (
status,filingRoute,patentType,applicantType). An unknown value rejects the item instead of degrading tonull. nullis refused on fields a patent cannot live without:office,patentType,applicationDate,applicationNumber,renewalsManagedFrom. Omit them to leave the value unchanged.- A creation must provide
office,patentType,applicationDateandapplicationNumber; a create item missing one is rejected withIncomplete CREATE: missing <fields>.renewalsManagedFromis not required on a create: when omitted, Renewr derives the annuity base date from the office's rules; provide it whenever your IPMS knows it. providerId: nullon an update is refused: your identity reference does not get erased by a sync.
A rejected item costs nothing: rejection happens before any write, and the reason string in the response names the field and the problem.
Inline or background
The batch size picks the processing mode. The pivot is 100 items, and it is a routing threshold rather than a cap: a request is never refused for its size.
| Batch size | Response | What you get |
|---|---|---|
| Up to 100 items | 201 Created | Final triage outcomes for every item, inline in the response |
| More than 100 items | 202 Accepted | The batch envelope with an importId; outcomes come from polling |
Poll a batch with GET /patents/sync/{importId}. The response carries the batch status, live counters, and one page of per-item outcomes in the order of your POST body, paginated with the standard ?currentPage=&itemsPerPage= parameters (default and cap: 100 per page). The first page of an inline batch is exactly what the POST already answered.
Read the batch status as two milestones:
PENDING/PROCESSING: Renewr is still reading the import. Keep polling; a few seconds between polls is plenty.TRIAGED: every item has been classified. Counters are final; items staged for review still await a decision.SETTLED: nothing left to wait on for this batch, every item reached a final state.ERROR: the batch finished but at least one item could not be recorded at all. Contact support with theimportId.
Item outcomes are not frozen with the batch: an item staged at triage moves to ACCEPTED or REJECTED on a later poll once a reviewer decides. Re-poll the batch when you want the decisions; an accepted creation carries the renewrPatentId of the new patent at that point. The five outcomes and what to do with each are covered in Change requests & review.
Idempotence and safe retries
externalImportRef is optional; provide it and the POST becomes replayable. Renewr fingerprints the items (order-sensitive for the array, insensitive to JSON key order) and compares on every POST carrying the same reference:
| Situation | Response |
|---|---|
| New reference | Normal processing |
| Same reference, same items | Replay: the stored batch state is returned, nothing is reprocessed (202 if still running, 201 otherwise) |
| Same reference, different items | 409 Conflict, code conflict, with the existingBatchId extension |
| Two concurrent POSTs, same reference | One wins; the other resolves against the winner's batch (replay or 409), never a 500 |
This makes the crash story simple. If your push times out or your process dies before reading the response, re-POST the same reference with the same items: you get the state of the batch that is already running (or finished) instead of a duplicate import. A 409 conflict in that flow is a signal that your reference generation reused a value for different content; mint a new reference rather than mutating the items under an old one.
One reference per logical export
Derive externalImportRef from your export run (a job id, a snapshot timestamp), never from the wall clock at request time. The reference is what welds "this exact content" to "this batch" across retries.
Batches also survive Renewr-side interruptions: an inline batch cut mid-flight is picked up and finished in the background, and re-polling the importId always shows the true state.
Your numbers and Renewr's numbers
Patent numbers (applicationNumber, publicationNumber, grantPublicationNumber, pctApplicationNumber) exist in two forms with different owners:
- Your form, exactly as your IPMS stores it. This is what you push, and what every read returns in those same four fields: you always read back what you pushed, without normalization, so your mirror never sees phantom diffs on numbers.
- The office-standard form, required by the IP offices for official payments. Renewr operators maintain it in the read-only
officialNumbersobject of the patent read model.
The sync channel only ever touches your form. An item that includes officialNumbers is rejected (Forbidden field: officialNumbers). And because the office-standard form may need re-deriving when your number changes, any change to a number field goes to review rather than applying automatically, whatever the office. Details in Change requests & review.
Budgeting the calls
A push costs one call, plus one call per poll of the status endpoint. Both count against your key's daily quota like any other call, and carry the usual RateLimit-* headers. A full-portfolio push of 5 000 patents is one POST and a handful of polls; the expensive habit to avoid is polling a large batch in a tight loop. See Authentication & limits.
Related pages
- Change requests & review: what the five outcomes mean and what happens after
STAGED - Keeping data in sync: the read half; mirror Renewr data back into your systems
- Synchronize your IPMS with Renewr: the full push-poll-reconcile loop as a recipe
POST /patents/syncandGET /patents/sync/{importId}: full schemas- Errors: the problem+json envelope and the
conflictcode