Documentation menu

Authentication

Every connection to MEV Alpha Store is authenticated. Credentials are issued per Client and may not be shared or resold (see Terms).

Credential type

You authenticate with an API key issued for your account, for example mev_live_3f9a2c7e1b8d4f60a5c9e2b7d1f4a8c3. One key covers every product in your offer.

As an additional layer, the key can be restricted to an allowlist of the public IP addresses of your servers. Send the addresses to our support when you request access or when your servers change.

InterfaceHow the key is passed
gRPC (Shreds)Metadata entry x-api-key
Private Orderflow over gRPCReversed: our relayer signs in to your server with its identity key. See gRPC push
WebSocketHTTP header x-api-key on the upgrade request
Private TPU Send (HTTPS)HTTP header x-api-key

The key is never sent in the URL, so it does not end up in proxy logs or browser history.

gRPC

Add the key as metadata to every call. The easiest way is a client interceptor, so that the key is attached in one place.

rust
use tonic::{metadata::MetadataValue, service::Interceptor, Request, Status};

#[derive(Clone)]
pub struct ApiKey(MetadataValue<tonic::metadata::Ascii>);

impl ApiKey {
    pub fn from_env() -> Self {
        let key = std::env::var("MEV_ALPHA_KEY").expect("MEV_ALPHA_KEY is not set");
        Self(key.parse().expect("invalid API key"))
    }
}

impl Interceptor for ApiKey {
    fn call(&mut self, mut req: Request<()>) -> Result<Request<()>, Status> {
        req.metadata_mut().insert("x-api-key", self.0.clone());
        Ok(req)
    }
}

// let client = ShredStreamClient::with_interceptor(channel, ApiKey::from_env());
ts
import { credentials, Metadata } from "@grpc/grpc-js";

const callCreds = credentials.createFromMetadataGenerator((_params, callback) => {
  const md = new Metadata();
  md.set("x-api-key", process.env.MEV_ALPHA_KEY!);
  callback(null, md);
});

// TLS channel credentials combined with the API key on every call
export const grpcCredentials = credentials.combineChannelCredentials(
  credentials.createSsl(),
  callCreds,
);

WebSocket

Pass the key as a header when you open the connection.

ts
import WebSocket from "ws";

const ws = new WebSocket(process.env.MEV_SHREDS_WS!, {
  headers: { "x-api-key": process.env.MEV_ALPHA_KEY! },
});

Browsers cannot set custom headers on WebSocket connections. Connect from your server, not from a browser.

Private TPU Send

Send the key as a header with every request.

bash
curl -s "$MEV_SEND_URL" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $MEV_ALPHA_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'

You never need to share the private keys of your trading wallets. Private TPU Send accepts transactions that you have already signed.

Authentication errors

SituationgRPCWebSocketHTTPS
Missing or invalid keyUNAUTHENTICATEDUpgrade rejected with HTTP 401HTTP 401
Key valid, IP address not allowlistedPERMISSION_DENIEDUpgrade rejected with HTTP 403HTTP 403
Product not included in your offerPERMISSION_DENIEDUpgrade rejected with HTTP 403HTTP 403

Do not retry authentication errors in a loop. Check the key and your server's public IP address, then contact support. See Errors for all status codes.

Rotating credentials

  • Contact our support to rotate or revoke credentials: @ZoriDev.
  • Rotate immediately if a credential may have been exposed.
  • Store credentials in environment variables or a secret manager. Never commit them to a repository.
  • Do not log full keys. If you need to identify a key in logs, log only its last four characters.

Our team will never message you first or ask for private keys. Always verify that you are speaking with @ZoriDev.

Need help or access? Contact our support on Telegram.

Contact