An API that connects multiple Microsoft services, enabling data access and automation across platforms
Hi Paul,
The report is unusually complete, so I will go straight to the three things I think you are missing rather than repeat what you have already ruled out.
First, and this changes how you should frame the escalation: the API reference does not promise the behaviour you are measuring against. On the driveItem: invite page the only statement about guest provisioning is the negative one, that new guests cannot be invited using app-only access and existing guests can. There is no line anywhere in the delegated section saying that a first-time external recipient gets provisioned as a B2B guest. MC1243549 describes the sharing experience and which authentication stack it uses, not the contract of this endpoint. So "Graph is defective against documented behaviour" is a weaker case than it looks, and support can deflect it. "The web UI and SP.Web.ShareObject provision the guest, Graph does not, and the reference is silent on whether it should" is accurate, harder to close, and it forces either a fix or a documentation statement. Either outcome is useful to you.
Second, there is one test that would make your isolation argument airtight. Call POST https://graph.microsoft.com/v1.0/invitations directly, delegated, same tenant, same recipient, same signed-in user. If that returns 201 and the guest appears in the directory, you have proved the Entra side is healthy and that the failure lives entirely in the call SharePoint makes into the Invitation Manager. Put that next to the absence of any "Invite external user" event in the audit log and you have a two-line reproduction that nobody can attribute to your tenant configuration.
Third, the supported Graph-only route you asked for probably exists, in two steps, and it is better than depending on ShareObject.
Provision the guest first with POST /invitations, then issue the /invite call you already have. Your own results table is the evidence this should work: when the recipient is already a guest in the tenant you get 200 OK. The delegated permission is User.Invite.All, inviteRedirectUrl is required in the body, and sendInvitationMessage can be set to false, so you keep the no-email behaviour you get today from sendInvitation: false. Worth knowing that this does not need an admin role in the normal case. The reference says it plainly:
"Both nonadmin member users and guest users can invite guests if the tenant admin hasn't restricted the default user permissions."
Guest Inviter, Directory Writers or User Administrator are only needed where a tenant has restricted that default, which is worth checking per customer tenant since you work across several.
One caveat I want to be explicit about, because it decides whether this is a fix or just a narrower bug report. Your table proves 200 OK for a recipient who is already a redeemed guest. With sendInvitationMessage set to false the newly created guest sits at PendingAcceptance and has not redeemed. So the case you need to test is /invite against a guest that exists but has not yet redeemed. If that returns 200, the two-step sequence replaces ShareObject entirely and you are done. If it returns 400 sharingFailed as well, then the defect is more specific than you currently describe it, because it would mean SharePoint is failing on redemption state rather than on existence, and that is a much sharper thing to hand to support.
Last thing, and only to save you a detour. There is a separate and currently undocumented problem going around where guest invitations stop working tenant-wide, and it looks superficially similar enough that people get sent down that path. It is not what you have. That one is a 403 from POST /invitations carrying the message "Invitations are blocked for this directory due to suspicious activity", it begins only after a number of successful invitations somewhere between eight and eleven, and it affects the Entra invitation path itself. Yours is a 400 sharingFailed from the very first attempt, on every tenant, with the Entra path apparently untouched. Different failure, different layer. If the POST /invitations test in step two comes back 201, you can also stop worrying about that one entirely.
If you do run that test, I would be interested in the result, since the redemption-state question above is the part that is genuinely unknown.