import { ExampleTabs } from '@/components/api-docs/example-tabs'; import { Code, FieldList, Guide, GuideSection, Snippet, } from '@/components/api-docs/guide'; import type { ApiDocsExample, ApiDocsSnippet } from '@/types'; export function Authentication({ signing, snippets, }: { signing: ApiDocsExample[]; snippets: Record; }) { return (

Each endpoint of the reference says which it is.

Your app keeps its own SSH key, made for it. It doesn't need to be on anyone's GitHub account, and a key that is only on GitHub can't sign API requests.

Then open https://dev-null.sh/mobile/authorize{' '} in a browser, the way an OAuth app would, with PKCE:

The key's, as ssh-keygen -lf{' '} prints it: SHA256:… ), }, { name: 'device_name', children: 'Where the key lives, shown on the approval page', }, { name: 'app_name', children: 'Optional. Your app, so people can tell apps apart in their devices', }, { name: 'app_id', children: ( <> Optional. A stable platform and identifier, like macos:sh.dev-null.mac ), }, { name: 'code_challenge', children: ( <> The SHA-256 of your verifier, base64url without padding, 43 characters, with{' '} code_challenge_method=S256 ), }, { name: 'state', children: 'Anything, sent back as it is', }, { name: 'redirect_uri', children: ( <> Where the code goes:{' '} http://127.0.0.1:<port>{' '} your app listens on. devnull://{' '} is the /dev/null apps' own. ), }, ]} />

The person signs in with GitHub if they need to, checks the fingerprint and approves. The browser then goes to your{' '} redirect_uri with a code and your{' '} state, or with error=access_denied . Redeem the code with POST /devices, signed with the new key, its body{' '} {'{"code": "…", "code_verifier": "…"}'}. The key is now one of their devices, until they revoke it in Settings → Devices.

Only signing in uses POST /devices, so the reference leaves it out with the other endpoints only the apps need to work.

Every request signs these five lines with the key, as an SSH signature in the devnull-api namespace:

The path and query are exactly the ones you request, from the root: /api/v1/search/commits?q=laravel. The body is exactly the bytes you send, as JSON with{' '} Content-Type: application/json, or nothing when there is none.

Every signed example of the reference calls one of these, with its method, path and body:

A request with images or a voice note is multipart, with nothing else in it: the JSON as a payload file part of type application/json (with curl,{' '} -F 'payload=@body.json;type=application/json' ), and either the images in images[] or the voice note in voice, never both. The signed message then has one more line before the body, the SHA-256 of each file, in hex, comma separated in the order they are attached, and the namespace is{' '} devnull-api-images.

Someone has to accept the commit rules once, in the web composer, before an app can commit for them. Until then, commits answer commit_rules_required.

); }