Etsy returns 403 'Shared secret is required in x-api-key header' when the keystring is used on resource endpoints: the keystring is only the OAuth client id. Store the shared secret alongside it (Settings form + env fallback) and send it as x-api-key on users/me and receipt requests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
28 lines
1 KiB
TypeScript
28 lines
1 KiB
TypeScript
import mongoose, { Document, Schema } from 'mongoose';
|
|
|
|
// Per-user Etsy app credentials, entered in the Settings UI.
|
|
// Falls back to ETSY_API_KEY / ETSY_REDIRECT_URI env vars when absent.
|
|
export interface IEtsySettings extends Document {
|
|
userId: mongoose.Types.ObjectId;
|
|
apiKey: string;
|
|
// Etsy requires the app's shared secret in the x-api-key header for API
|
|
// calls; the keystring (apiKey) is the OAuth client id
|
|
sharedSecret?: string;
|
|
redirectUri: string;
|
|
dateUpdated: Date;
|
|
}
|
|
|
|
const EtsySettingsSchema: Schema = new Schema({
|
|
userId: { type: Schema.Types.ObjectId, ref: 'User', required: true, unique: true, index: true },
|
|
apiKey: { type: String, required: true, trim: true },
|
|
sharedSecret: { type: String, trim: true },
|
|
redirectUri: { type: String, required: true, trim: true },
|
|
dateUpdated: { type: Date, default: Date.now },
|
|
});
|
|
|
|
EtsySettingsSchema.pre('save', function (next) {
|
|
this.dateUpdated = new Date();
|
|
next();
|
|
});
|
|
|
|
export default mongoose.model<IEtsySettings>('EtsySettings', EtsySettingsSchema);
|