docs(documents): define supported file types and document rejection responses - #861
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
✱ Stainless preview builds for gridThis PR will update the cli go kotlin openapi php python ruby typescript
|
| message: | ||
| type: string | ||
| description: Error message | ||
| precheckErrors: |
There was a problem hiding this comment.
are you sure precheckErrors is returned? Can you verify from the webdev repo?
There was a problem hiding this comment.
Verified — it is returned, and the trace turned up one detail worth having in the schema.
Both handlers raise it (sparkcore/grid/api_handlers/):
raise GridException(
reason=...,
error_code=ErrorCode.DOCUMENT_REJECTED,
details={"precheckErrors": ex.errors},
)upload_document.py:167 on SumsubDocumentRejectedError, and replace_document.py:133 on the same. ErrorCode.DOCUMENT_REJECTED is declared http_status_code=422 in grid/exceptions.py:52, so the 422 pairing is right.
The path to the wire: both routes are wrapped in @grid_api, whose handler at grid_api.py:695-707 does jsonify(ex.to_dict()) with ex.http_status_code. And GridException.to_dict() does:
if self.details:
body.update(self.details)That's update, not body["details"] = ... — so precheckErrors is spread at the top level of the error body, not nested under details. That matches this schema as written, which is what I wanted to confirm rather than assume.
Independent confirmation from the consumer side: the dashboard reads it from the top level first in js/apps/private/site/src/uma-nage/gridApiErrorParsing.ts:52, with the nested positions only as fallbacks.
I also checked the four labels I documented rather than leaving them plausible-looking: dataNotReadable, screenshot, grayscale, and documentExpired all appear in the provider-label map in uma-nage/kyb/kybValidation.ts.
One thing I removed while here: the sentence claiming Grid "cannot break one down further" — that's the same claim you asked to drop, so it went with the rest.
| - be unexpired | ||
|
|
||
| Supported file types: PDF, JPEG, PNG. Maximum file size: 10 MB. | ||
| Grid runs no image analysis of its own and sets no resolution floor. The |
There was a problem hiding this comment.
remove this grid runs no image analysis text
There was a problem hiding this comment.
Removed — and per your follow-up in Slack, everywhere it appeared, not just here:
- this description (
POST /documents) PUT /documents/{documentId}, which carried the same paragraphBaseDocumentRequest.yaml, the one you first pointed atError422.yaml, whereprecheckErrorsrestated the claim ("Grid does not compute these labels and cannot break one down further")
grep for "image analysis" and "resolution floor" across openapi/ and mintlify/ now returns nothing. The concrete photo requirements stay, since those are what an integrator can act on.
| $ref: ../../components/schemas/errors/Error404.yaml | ||
| '422': | ||
| description: >- | ||
| The verification provider rejected the file. `precheckErrors` names |
There was a problem hiding this comment.
verify the precheckErrors is actually returned
There was a problem hiding this comment.
Verified — it is returned on this endpoint too. replace_document.py:133 raises GridException(error_code=ErrorCode.DOCUMENT_REJECTED, details={"precheckErrors": e.errors}) on SumsubDocumentRejectedError, the same shape as the upload path.
Worth noting the two differ in one respect that this description already reflects: replace rolls back the metadata mutation before raising, so a rejected PUT leaves the stored document on its previous file and metadata.
Full trace through to_dict() and the @grid_api wrapper — including the finding that precheckErrors lands at the top level of the body rather than under details — is in the Error422.yaml thread, so I won't duplicate it here.
|
⚡ Revision log — updated in place, latest first. Revision 1
|
…esponses
Publish the file contract for POST /documents and PUT /documents/{documentId}:
the three accepted content types, that matching is on the multipart
Content-Type rather than the file extension, the 10 MB request body cap, and
the photo requirements a document has to meet to pass the provider's upload
screen.
Add the 422 DOCUMENT_REJECTED response both operations already return, with
the precheckErrors array that names each problem found.
Remove the paragraph from the BaseDocumentRequest file field and from both document endpoint descriptions, along with the restatement on precheckErrors, and rebundle. Co-Authored-By: pengying <pengying@users.noreply.github.com>
0745e19 to
05a46b0
Compare

Summary
The Grid docs told integrators only "Supported file types: PDF, JPEG, PNG. Maximum file size: 10 MB." A partner hit a
422 DOCUMENT_REJECTED/dataNotReadableon a passport upload, asked what the minimum image requirements are, and we had nothing published to point them at. This defines the file contract onPOST /documentsandPUT /documents/{documentId}.Changes
File types. Named as the exact content types the API matches on —
application/pdf,image/jpeg,image/png— and stated that matching is on the multipart part'sContent-Type, not the filename extension. That distinction is load-bearing: an integrator sending a HEIC aspassport.jpg, or any client that omits a per-part type, gets a400with no obvious cause.image/heic,image/webp, andimage/tiffare called out as rejected, since those are what a phone camera roll actually produces.Photo requirements. The endpoint descriptions now list what a document image must satisfy to pass the provider's upload screen: whole document in frame with all four corners, in focus and free of glare, in color, an actual photo or scan rather than a screen capture or an edited image, and unexpired. Each corresponds to a rejection label the provider can return.
422 DOCUMENT_REJECTED. Both operations already return this, and neither documented it. AddsError422with theprecheckErrorsarray and the meaning of the common labels.precheckErrorswas verified against the implementation, not inferred — see Verification below. The two rejection paths are also distinguished, because they need different fixes: a422on upload creates no document, so it is retried withPOST, while a document rejected later during review has an ID and should be replaced withPUTso the rejected file is marked inactive.Verification
make lintpasses: 0 errors, exit 0. Warning and info counts matchmainexactly (148 / 518), apart from 3 newschema-properties-have-examplesinfos onError422— the same three every existingError4xxschema already emits.make buildrebundles cleanly and is idempotent;openapi.yamlandmintlify/openapi.yamlare identical.precheckErrorsis really returned, traced end to end inwebdev: bothgrid/api_handlers/upload_document.pyandreplace_document.pyraiseGridException(error_code=ErrorCode.DOCUMENT_REJECTED, details={"precheckErrors": ex.errors});ErrorCode.DOCUMENT_REJECTEDis defined withhttp_status_code=422; the@grid_apidecorator that wraps both routes serializes it viajsonify(ex.to_dict())withex.http_status_code; andGridException.to_dict()doesbody.update(self.details), which placesprecheckErrorsat the top level of the response body rather than nested underdetails— matching the schema as written. The dashboard client reads it from that top-level position (gridApiErrorParsing.ts). The four documented labels (dataNotReadable,screenshot,grayscale,documentExpired) all appear in the client's provider-label map inkyb/kybValidation.ts.One correction this surfaced
The old "max 10 MB" is accurate as a file limit but the enforcement is a whole-request cap set slightly above it, so the file limit is not checked directly. The docs now state the 10 MB file limit, which is the number an integrator should build against.
Worth flagging separately, as code changes rather than doc ones: when the provider rejects an oversized file, Grid passes through a message telling the caller to reduce it to under 5 MB, which contradicts the 10 MB we publish. Any file between roughly 5 and 10 MB can pass Grid's own checks and then fail upstream with that message. I have not changed either number here — reconciling them is a behavior decision, not a docs one.
Test plan
make lintpasses with 0 errorsmake buildproduces no diff on re-runRequested by @pengying